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
This commit is contained in:
parent
e18b1f330a
commit
e1145d7ea4
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user