aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugh Dickins <hughd@google.com>2010-10-24 17:32:47 -0700
committerKarel Zak <kzak@redhat.com>2010-11-01 16:35:31 +0100
commitc2301380b4d61921971f89661088d1dab7c70ccd (patch)
tree249f6a38adda7ec24d70cab99b9f09ac46e613b2
parent3924d0f169525270e20b6183ee67bca5822d0291 (diff)
swapon: add "discard" support
In kernel 2.6.36 (and in stable kernel 2.6.35.5) I made a tiny change to the swapon(const char *path, int swapflags) system call interface: kernel commit 3399446632739fcd05fd8b272b476a69c6e6d14a swap: discard while swapping only if SWAP_FLAG_DISCARD As things stand at present, we could just remove the swap discard support; but since several filesystems (including ext4 and btrfs and fat) are offering a "discard" mount option, I thought swap should take the same course, and offer a "--discard" or "-d" option to swapon(8). [kzak@redhat.com: - update swapon.8 man page - use for -d the same logic as for -p] Signed-off-by: Hugh Dickins <hughd@google.com> Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--mount/swapon.811
-rw-r--r--mount/swapon.c40
2 files changed, 39 insertions, 12 deletions
diff --git a/mount/swapon.8 b/mount/swapon.8
index 595198d..e35c6e5 100644
--- a/mount/swapon.8
+++ b/mount/swapon.8
@@ -54,6 +54,7 @@ Enable/disable:
.br
.in +5
.B swapon
+.RB [ \-d ]
.RB [ \-f ]
.RB [ \-p
.IR priority ]
@@ -111,6 +112,16 @@ All devices marked as ``swap'' in
are made available, except for those with the ``noauto'' option.
Devices that are already being used as swap are silently skipped.
.TP
+.B "\-d, \-\-discard"
+Swapping will discard clusters of swap pages in between freeing them
+and re-writing to them, if the swap device supports that.
+The
+.I /etc/fstab
+mount option
+.BI discard
+may be also used to enable discard flag.
+
+.TP
.B "\-e, \-\-ifexists"
Silently skip devices that do not exist.
The
diff --git a/mount/swapon.c b/mount/swapon.c
index 45cd266..d8fad0b 100644
--- a/mount/swapon.c
+++ b/mount/swapon.c
@@ -30,6 +30,10 @@
# include <sys/swap.h>
#endif
+#ifndef SWAP_FLAG_DISCARD
+# define SWAP_FLAG_DISCARD 0x10000 /* discard swap cluster after use */
+#endif
+
#ifndef SWAPON_HAS_TWO_ARGS
/* libc is insane, let's call the kernel */
# include <sys/syscall.h>
@@ -54,6 +58,7 @@ enum {
int all;
int priority = -1; /* non-prioritized swap by default */
+int discard;
/* If true, don't complain if the device/file doesn't exist */
int ifexists;
@@ -65,6 +70,7 @@ char *progname;
static struct option longswaponopts[] = {
/* swapon only */
{ "priority", required_argument, 0, 'p' },
+ { "discard", 0, 0, 'd' },
{ "ifexists", 0, 0, 'e' },
{ "summary", 0, 0, 's' },
{ "fixpgsz", 0, 0, 'f' },
@@ -92,7 +98,7 @@ static void
swapon_usage(FILE *fp, int n) {
fprintf(fp, _("\nUsage:\n"
" %1$s -a [-e] [-v] [-f] enable all swaps from /etc/fstab\n"
- " %1$s [-p priority] [-v] [-f] <special> enable given swap\n"
+ " %1$s [-p priority] [-d] [-v] [-f] <special> enable given swap\n"
" %1$s -s display swap usage summary\n"
" %1$s -h display help\n"
" %1$s -V display version\n\n"), progname);
@@ -471,7 +477,7 @@ err:
}
static int
-do_swapon(const char *orig_special, int prio, int canonic) {
+do_swapon(const char *orig_special, int prio, int fl_discard, int canonic) {
int status;
const char *special = orig_special;
int flags = 0;
@@ -497,6 +503,9 @@ do_swapon(const char *orig_special, int prio, int canonic) {
<< SWAP_FLAG_PRIO_SHIFT);
}
#endif
+ if (fl_discard)
+ flags |= SWAP_FLAG_DISCARD;
+
status = swapon(special, flags);
if (status < 0)
warn(_("%s: swapon failed"), orig_special);
@@ -511,15 +520,17 @@ cannot_find(const char *special) {
}
static int
-swapon_by_label(const char *label, int prio) {
+swapon_by_label(const char *label, int prio, int dsc) {
const char *special = fsprobe_get_devname_by_label(label);
- return special ? do_swapon(special, prio, CANONIC) : cannot_find(label);
+ return special ? do_swapon(special, prio, dsc, CANONIC) :
+ cannot_find(label);
}
static int
-swapon_by_uuid(const char *uuid, int prio) {
+swapon_by_uuid(const char *uuid, int prio, int dsc) {
const char *special = fsprobe_get_devname_by_uuid(uuid);
- return special ? do_swapon(special, prio, CANONIC) : cannot_find(uuid);
+ return special ? do_swapon(special, prio, dsc, CANONIC) :
+ cannot_find(uuid);
}
static int
@@ -574,7 +585,7 @@ swapon_all(void) {
while ((fstab = getmntent(fp)) != NULL) {
const char *special;
int skip = 0, nofail = ifexists;
- int pri = priority;
+ int pri = priority, dsc = discard;
char *opt, *opts;
if (!streq(fstab->mnt_type, MNTTYPE_SWAP))
@@ -586,6 +597,8 @@ swapon_all(void) {
opt = strtok(NULL, ",")) {
if (strncmp(opt, "pri=", 4) == 0)
pri = atoi(opt+4);
+ if (strcmp(opt, "discard") == 0)
+ dsc = 1;
if (strcmp(opt, "noauto") == 0)
skip = 1;
if (strcmp(opt, "nofail") == 0)
@@ -605,7 +618,7 @@ swapon_all(void) {
if (!is_in_proc_swaps(special) &&
(!nofail || !access(special, R_OK)))
- status |= do_swapon(special, pri, CANONIC);
+ status |= do_swapon(special, pri, dsc, CANONIC);
free((void *) special);
}
@@ -638,7 +651,7 @@ main_swapon(int argc, char *argv[]) {
int status = 0;
int c, i;
- while ((c = getopt_long(argc, argv, "ahefp:svVL:U:",
+ while ((c = getopt_long(argc, argv, "ahdefp:svVL:U:",
longswaponopts, NULL)) != -1) {
switch (c) {
case 'a': /* all */
@@ -656,6 +669,9 @@ main_swapon(int argc, char *argv[]) {
case 'U':
addu(optarg);
break;
+ case 'd':
+ discard = 1;
+ break;
case 'e': /* ifexists */
ifexists = 1;
break;
@@ -690,13 +706,13 @@ main_swapon(int argc, char *argv[]) {
status |= swapon_all();
for (i = 0; i < llct; i++)
- status |= swapon_by_label(llist[i], priority);
+ status |= swapon_by_label(llist[i], priority, discard);
for (i = 0; i < ulct; i++)
- status |= swapon_by_uuid(ulist[i], priority);
+ status |= swapon_by_uuid(ulist[i], priority, discard);
while (*argv != NULL)
- status |= do_swapon(*argv++, priority, !CANONIC);
+ status |= do_swapon(*argv++, priority, discard, !CANONIC);
return status;
}