[RFC PATCH 02/02] swapon: add "cluster-discard" support

From: Rafael Aquini
Date: Mon May 20 2013 - 20:05:33 EST


Introduce a new swapon flag/option to support more flexible swap discard setup.
The --cluster-discard swapon(8) option can be used by a system admin to flag
sys_swapon() to perform page-cluster fine-grained discards.

This patch also changes the behaviour of swapon(8) --discard option, that now
will only be used to flag sys_swapon() batched discards will be issued at
swapon(8) time.

Signed-off-by: Rafael Aquini <aquini@xxxxxxxxxx>
---
sys-utils/swapon.8 | 19 ++++++++++++++++---
sys-utils/swapon.c | 34 ++++++++++++++++++++++++++--------
2 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/sys-utils/swapon.8 b/sys-utils/swapon.8
index 385bf5a..0c8ac69 100644
--- a/sys-utils/swapon.8
+++ b/sys-utils/swapon.8
@@ -112,10 +112,23 @@ 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
+.TP
+.B "\-c, \-\-cluster\-discard"
+Swapping will discard clusters of swap pages in between freeing them
+and re-writing to them, if the swap device supports that. This option
+also implies the
+.I \-d, \-\-discard
+swapon flag.
+The
+.I /etc/fstab
+mount option
+.BI cluster\-discard
+may be also used to enable this flag.
+
+.TP
.B "\-d, \-\-discard"
-Discard freed swap pages before they are reused, if the swap
-device supports the discard or trim operation. This may improve
-performance on some Solid State Devices, but often it does not.
+Enables swap discards, if the swap device supports that, and performs
+a batch discard operation for the swap device at swapon time.
The
.I /etc/fstab
mount option
diff --git a/sys-utils/swapon.c b/sys-utils/swapon.c
index f1e2433..a71f69e 100644
--- a/sys-utils/swapon.c
+++ b/sys-utils/swapon.c
@@ -34,7 +34,11 @@
#endif

#ifndef SWAP_FLAG_DISCARD
-# define SWAP_FLAG_DISCARD 0x10000 /* discard swap cluster after use */
+# define SWAP_FLAG_DISCARD 0x10000 /* enable discard for swap */
+#endif
+
+#ifndef SWAP_FLAG_DISCARD_CLUSTER
+# define SWAP_FLAG_DISCARD_CLUSTER 0x20000 /* discard swap cluster after use */
#endif

#ifndef SWAP_FLAG_PREFER
@@ -70,7 +74,7 @@ enum {

static int all;
static int priority = -1; /* non-prioritized swap by default */
-static int discard;
+static int discard = 0; /* don't send swap discards by default */

/* If true, don't complain if the device/file doesn't exist */
static int ifexists;
@@ -570,8 +574,11 @@ static int do_swapon(const char *orig_special, int prio,
<< SWAP_FLAG_PRIO_SHIFT);
}
#endif
- if (fl_discard)
+ if (fl_discard) {
flags |= SWAP_FLAG_DISCARD;
+ if (fl_discard > 1)
+ flags |= SWAP_FLAG_DISCARD_CLUSTER;
+ }

status = swapon(special, flags);
if (status < 0)
@@ -615,8 +622,14 @@ static int swapon_all(void)

if (mnt_fs_get_option(fs, "noauto", NULL, NULL) == 0)
continue;
- if (mnt_fs_get_option(fs, "discard", NULL, NULL) == 0)
- dsc = 1;
+ if (mnt_fs_get_option(fs, "discard", NULL, NULL) == 0) {
+ if !(dsc)
+ dsc = 1;
+ }
+ if (mnt_fs_get_option(fs, "cluster-discard", NULL, NULL) == 0) {
+ if (!dsc || dsc == 1)
+ dsc = 2;
+ }
if (mnt_fs_get_option(fs, "nofail", NULL, NULL) == 0)
nofail = 1;
if (mnt_fs_get_option(fs, "pri", &p, NULL) == 0 && p)
@@ -647,7 +660,8 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)

fputs(USAGE_OPTIONS, out);
fputs(_(" -a, --all enable all swaps from /etc/fstab\n"
- " -d, --discard discard freed pages before they are reused\n"
+ " -c, --cluster-discard discard freed pages before they are reused, while swapping\n"
+ " -d, --discard discard freed pages before they are reused, all at once, at swapon time\n"
" -e, --ifexists silently skip devices that do not exist\n"
" -f, --fixpgsz reinitialize the swap space if necessary\n"
" -p, --priority <prio> specify the priority of the swap device\n"
@@ -696,6 +710,7 @@ int main(int argc, char *argv[])

static const struct option long_opts[] = {
{ "priority", 1, 0, 'p' },
+ { "cluster-discard", 0, 0, 'c' },
{ "discard", 0, 0, 'd' },
{ "ifexists", 0, 0, 'e' },
{ "summary", 0, 0, 's' },
@@ -719,7 +734,7 @@ int main(int argc, char *argv[])
mnt_init_debug(0);
mntcache = mnt_new_cache();

- while ((c = getopt_long(argc, argv, "ahdefp:svVL:U:",
+ while ((c = getopt_long(argc, argv, "ahcdefp:svVL:U:",
long_opts, NULL)) != -1) {
switch (c) {
case 'a': /* all */
@@ -738,8 +753,11 @@ int main(int argc, char *argv[])
case 'U':
add_uuid(optarg);
break;
+ case 'c':
+ discard += 2;
+ break;
case 'd':
- discard = 1;
+ discard += 1;
break;
case 'e': /* ifexists */
ifexists = 1;
--
1.7.11.7

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/