aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Moore <dougm@FreeBSD.org>2019-06-22 03:16:01 +0000
committerDoug Moore <dougm@FreeBSD.org>2019-06-22 03:16:01 +0000
commita616b25342fe1ceaa2bb7c68d9791f6586656fed (patch)
treeac967fdccd994b44abc70806ef55ee8295961017
parentdf8406543fab98a6706bb41f3093863b93d92b91 (diff)
downloadsrc-a616b25342fe1ceaa2bb7c68d9791f6586656fed.tar.gz
src-a616b25342fe1ceaa2bb7c68d9791f6586656fed.zip
Modify swapon(8) to invoke BIO_DELETE to trim swap devices, either if
'-E' appears on the swapon command line, or if "trimonce" appears as an fstab option. Discussed at: BSDCAN Tested by: markj Reviewed by: markj Approved by: markj (mentor) Differential Revision:https://reviews.freebsd.org/D20599
Notes
Notes: svn path=/head/; revision=349286
-rw-r--r--sbin/swapon/swapon.89
-rw-r--r--sbin/swapon/swapon.c59
-rw-r--r--share/man/man5/fstab.56
3 files changed, 67 insertions, 7 deletions
diff --git a/sbin/swapon/swapon.8 b/sbin/swapon/swapon.8
index 058f681ce5ce..f69dd484a93b 100644
--- a/sbin/swapon/swapon.8
+++ b/sbin/swapon/swapon.8
@@ -28,7 +28,7 @@
.\" @(#)swapon.8 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd October 21, 2016
+.Dd June 21, 2019
.Dt SWAPON 8
.Os
.Sh NAME
@@ -38,7 +38,7 @@
.Nm swapon
.Oo Fl F Ar fstab
.Oc
-.Fl aLq | Ar
+.Fl aLq | E Ar
.Nm swapoff
.Oo Fl F Ar fstab
.Oc
@@ -86,6 +86,11 @@ If the
option is used,
informational messages will not be
written to standard output when a swap device is added.
+The
+.Fl E
+option causes each of following devices to receive a
+.Dv BIO_DELETE
+command to mark all blocks as unused.
.Pp
The
.Nm swapoff
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index 83201535b4ab..c8904ade5a8f 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -43,6 +43,7 @@ static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/disk.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/mdioctl.h>
@@ -77,7 +78,7 @@ static int run_cmd(int *, const char *, ...) __printflike(2, 3);
static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
-static int qflag;
+static int Eflag, qflag;
int
main(int argc, char **argv)
@@ -100,7 +101,7 @@ main(int argc, char **argv)
doall = 0;
etc_fstab = NULL;
- while ((ch = getopt(argc, argv, "AadghklLmqsUF:")) != -1) {
+ while ((ch = getopt(argc, argv, "AadEghklLmqsUF:")) != -1) {
switch(ch) {
case 'A':
if (which_prog == SWAPCTL) {
@@ -121,6 +122,12 @@ main(int argc, char **argv)
else
usage();
break;
+ case 'E':
+ if (which_prog == SWAPON)
+ Eflag = 2;
+ else
+ usage();
+ break;
case 'g':
hflag = 'G';
break;
@@ -182,8 +189,10 @@ main(int argc, char **argv)
strstr(fsp->fs_mntops, "late") == NULL &&
late != 0)
continue;
+ Eflag |= (strstr(fsp->fs_mntops, "trimonce") != NULL);
swfile = swap_on_off(fsp->fs_spec, 1,
fsp->fs_mntops);
+ Eflag &= ~1;
if (swfile == NULL) {
ret = 1;
continue;
@@ -378,12 +387,22 @@ swap_on_geli_args(const char *mntops)
return (NULL);
}
} else if (strcmp(token, "notrim") == 0) {
+ if (Eflag) {
+ warn("Options \"notrim\" and "
+ "\"trimonce\" conflict");
+ free(ops);
+ return (NULL);
+ }
Tflag = " -T ";
} else if (strcmp(token, "late") == 0) {
/* ignore known option */
} else if (strcmp(token, "noauto") == 0) {
/* ignore known option */
- } else if (strcmp(token, "sw") != 0) {
+ } else if (strcmp(token, "sw") == 0) {
+ /* ignore known option */
+ } else if (strcmp(token, "trimonce") == 0) {
+ /* ignore known option */
+ } else {
warnx("Invalid option: %s", token);
free(ops);
return (NULL);
@@ -721,14 +740,42 @@ run_cmd(int *ofd, const char *cmdline, ...)
return (WEXITSTATUS(status));
}
+static void
+swap_trim(const char *name)
+{
+ struct stat sb;
+ off_t ioarg[2], sz;
+ int fd;
+
+ fd = open(name, O_WRONLY);
+ if (fd < 0)
+ errx(1, "Cannot open %s", name);
+ if (fstat(fd, &sb) < 0)
+ errx(1, "Cannot stat %s", name);
+ if (S_ISREG(sb.st_mode))
+ sz = sb.st_size;
+ else if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ if (ioctl(fd, DIOCGMEDIASIZE, &sz) != 0)
+ err(1, "ioctl(DIOCGMEDIASIZE)");
+ } else
+ errx(1, "%s has an invalid file type", name);
+ ioarg[0] = 0;
+ ioarg[1] = sz;
+ if (ioctl(fd, DIOCGDELETE, ioarg) != 0)
+ warn("ioctl(DIOCGDELETE)");
+ close(fd);
+}
+
static const char *
swap_on_off_sfile(const char *name, int doingall)
{
int error;
- if (which_prog == SWAPON)
+ if (which_prog == SWAPON) {
+ if (Eflag)
+ swap_trim(name);
error = swapon(name);
- else /* SWAPOFF */
+ } else /* SWAPOFF */
error = swapoff(name);
if (error == -1) {
@@ -759,6 +806,8 @@ usage(void)
fprintf(stderr, "usage: %s ", getprogname());
switch(orig_prog) {
case SWAPON:
+ fprintf(stderr, "[-F fstab] -aLq | [-E] file ...\n");
+ break;
case SWAPOFF:
fprintf(stderr, "[-F fstab] -aLq | file ...\n");
break;
diff --git a/share/man/man5/fstab.5 b/share/man/man5/fstab.5
index 062ab601851f..f4e9ce2b653e 100644
--- a/share/man/man5/fstab.5
+++ b/share/man/man5/fstab.5
@@ -216,6 +216,12 @@ then the special file is made available as a piece of swap
space by the
.Xr swapon 8
command at the end of the system reboot procedure.
+For swap devices, the keyword
+.Dq trimonce
+triggers the delivery of a
+.Dv BIO_DELETE
+command to the device to mark
+all blocks as unused.
For vnode-backed swap spaces,
.Dq file
is supported in the