discard change to swapon(2) and swapon(8)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Karel, Michael,

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

I added this definition to the kernel's include/linux/swap.h:
#define SWAP_FLAG_DISCARD	0x10000 /* discard swap cluster after use */
(which I think needs to find its way into /usr/include/sys/swap.h somehow);
and if that bit is set in swapflags (previously devoted to swap priority),
then swapping will discard clusters of swap pages in between freeing them
and re-writing to them, if the swap device supports that (discard or trim
being notification from OS to device that stale data is no longer needed).

(No error occurs if the device does not support discard, and the only sign
that it is discarding is "D" at the end of the kernel's "Adding XXXk swap"
message.  And that flag only governs discarding while swapping: whether
or not it is supplied, every swapon tries to discard the entire swap area,
less its swap header page - that will normally be an efficient operation.
Earlier kernels than 2.6.35.5 will just ignore the flag.)

The story behind is this.  In 2.6.29 I implemented this behaviour for any
device that supports discard, before having any real SSD that supported
it: in the hope that it would give a useful boost to swapping on SSD once
device support arrived.  About a year ago, OCZ implemented discard in their
Vertex, then Intel in their X25: testing around 2.6.32, the OCZ showed
measurable (though disappointing) benefit, the Intel arguable benefit.

But since then, the kernel's block-layer support for discard has gone
through a series of changes (with most recently a shift from reliance
on I/O barriers to waiting on completions), and the SSD firmwares have
been updated too.  With the result that once I tested again, shortly
after 2.6.35 came out (alerted by a bugreport from Nigel Cunningham),
it proved to be a disadvantage on the Intel, and a disaster on the OCZ
(even after a patch from hch removed the most obvious overhead).

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).

Below is the patch I tested with.  I could sign it off, except for that
#ifndef SWAP_FLAG_DISCARD business at the start (I'm rather hoping that
you, Karel, will have a hotline to getting that addition to sys/swap.h).
Something else questionable about it, is that final "if (all && discard)
swapon_usage(stderr, 1)" hunk: I'm not sure what's best when you
"swapon -a -d", given that /etc/fstab can itself say "discard" or not;
I took the easiest way to code it up, and made "swapon -a -d" an error.

I apologize to you both for taking so long to alert you (and sorry for
being so verbose! but I think the background makes more sense of it).
But as you can see from the above, there is no great urgency to adding
and documenting this support.

Thanks,
Hugh

--- util-linux-ng-2.18/mount/swapon.c.0	2010-06-14 02:19:19.000000000 -0700
+++ util-linux-ng-2.18/mount/swapon.c	2010-09-05 22:07:48.000000000 -0700
@@ -29,6 +29,9 @@
 #ifdef HAVE_SYS_SWAP_H
 # 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 */
@@ -54,6 +57,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 +69,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 +97,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);
@@ -493,6 +498,8 @@ do_swapon(const char *orig_special, int
 			   << SWAP_FLAG_PRIO_SHIFT);
 	}
 #endif
+	if (discard)
+		flags |= SWAP_FLAG_DISCARD;
 	status = swapon(special, flags);
 	if (status < 0)
 		warn(_("%s: swapon failed"), orig_special);
@@ -582,6 +589,8 @@ swapon_all(void) {
 		     opt = strtok(NULL, ",")) {
 			if (strncmp(opt, "pri=", 4) == 0)
 				pri = atoi(opt+4);
+			if (strcmp(opt, "discard") == 0)
+				discard = 1;
 			if (strcmp(opt, "noauto") == 0)
 				skip = 1;
 		}
@@ -605,6 +614,7 @@ swapon_all(void) {
 	}
 	fclose(fp);
 
+	discard = 0;
 	return status;
 }
 
@@ -632,7 +642,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 */
@@ -650,6 +660,9 @@ main_swapon(int argc, char *argv[]) {
 		case 'U':
 			addu(optarg);
 			break;
+		case 'd':
+			discard = 1;
+			break;
 		case 'e':               /* ifexists */
 		        ifexists = 1;
 			break;
@@ -680,6 +693,9 @@ main_swapon(int argc, char *argv[]) {
 	if (ifexists && (!all || strcmp(progname, "swapon")))
 		swapon_usage(stderr, 1);
 
+	if (all && discard)
+		swapon_usage(stderr, 1);
+
 	if (all)
 		status |= swapon_all();
 
--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux