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
|
.\" @(#)swapon.8 8.1 (Berkeley) 6/5/93
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd October 21, 2016
|
.Dd June 21, 2019
|
||||||
.Dt SWAPON 8
|
.Dt SWAPON 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -38,7 +38,7 @@
|
|||||||
.Nm swapon
|
.Nm swapon
|
||||||
.Oo Fl F Ar fstab
|
.Oo Fl F Ar fstab
|
||||||
.Oc
|
.Oc
|
||||||
.Fl aLq | Ar
|
.Fl aLq | E Ar
|
||||||
.Nm swapoff
|
.Nm swapoff
|
||||||
.Oo Fl F Ar fstab
|
.Oo Fl F Ar fstab
|
||||||
.Oc
|
.Oc
|
||||||
@ -86,6 +86,11 @@ If the
|
|||||||
option is used,
|
option is used,
|
||||||
informational messages will not be
|
informational messages will not be
|
||||||
written to standard output when a swap device is added.
|
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
|
.Pp
|
||||||
The
|
The
|
||||||
.Nm swapoff
|
.Nm swapoff
|
||||||
|
@ -43,6 +43,7 @@ static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93";
|
|||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/disk.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/mdioctl.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 enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
|
||||||
|
|
||||||
static int qflag;
|
static int Eflag, qflag;
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
@ -100,7 +101,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
doall = 0;
|
doall = 0;
|
||||||
etc_fstab = NULL;
|
etc_fstab = NULL;
|
||||||
while ((ch = getopt(argc, argv, "AadghklLmqsUF:")) != -1) {
|
while ((ch = getopt(argc, argv, "AadEghklLmqsUF:")) != -1) {
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
case 'A':
|
case 'A':
|
||||||
if (which_prog == SWAPCTL) {
|
if (which_prog == SWAPCTL) {
|
||||||
@ -121,6 +122,12 @@ main(int argc, char **argv)
|
|||||||
else
|
else
|
||||||
usage();
|
usage();
|
||||||
break;
|
break;
|
||||||
|
case 'E':
|
||||||
|
if (which_prog == SWAPON)
|
||||||
|
Eflag = 2;
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
hflag = 'G';
|
hflag = 'G';
|
||||||
break;
|
break;
|
||||||
@ -182,8 +189,10 @@ main(int argc, char **argv)
|
|||||||
strstr(fsp->fs_mntops, "late") == NULL &&
|
strstr(fsp->fs_mntops, "late") == NULL &&
|
||||||
late != 0)
|
late != 0)
|
||||||
continue;
|
continue;
|
||||||
|
Eflag |= (strstr(fsp->fs_mntops, "trimonce") != NULL);
|
||||||
swfile = swap_on_off(fsp->fs_spec, 1,
|
swfile = swap_on_off(fsp->fs_spec, 1,
|
||||||
fsp->fs_mntops);
|
fsp->fs_mntops);
|
||||||
|
Eflag &= ~1;
|
||||||
if (swfile == NULL) {
|
if (swfile == NULL) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
continue;
|
continue;
|
||||||
@ -378,12 +387,22 @@ swap_on_geli_args(const char *mntops)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
} else if (strcmp(token, "notrim") == 0) {
|
} else if (strcmp(token, "notrim") == 0) {
|
||||||
|
if (Eflag) {
|
||||||
|
warn("Options \"notrim\" and "
|
||||||
|
"\"trimonce\" conflict");
|
||||||
|
free(ops);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
Tflag = " -T ";
|
Tflag = " -T ";
|
||||||
} else if (strcmp(token, "late") == 0) {
|
} else if (strcmp(token, "late") == 0) {
|
||||||
/* ignore known option */
|
/* ignore known option */
|
||||||
} else if (strcmp(token, "noauto") == 0) {
|
} else if (strcmp(token, "noauto") == 0) {
|
||||||
/* ignore known option */
|
/* 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);
|
warnx("Invalid option: %s", token);
|
||||||
free(ops);
|
free(ops);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -721,14 +740,42 @@ run_cmd(int *ofd, const char *cmdline, ...)
|
|||||||
return (WEXITSTATUS(status));
|
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 *
|
static const char *
|
||||||
swap_on_off_sfile(const char *name, int doingall)
|
swap_on_off_sfile(const char *name, int doingall)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (which_prog == SWAPON)
|
if (which_prog == SWAPON) {
|
||||||
|
if (Eflag)
|
||||||
|
swap_trim(name);
|
||||||
error = swapon(name);
|
error = swapon(name);
|
||||||
else /* SWAPOFF */
|
} else /* SWAPOFF */
|
||||||
error = swapoff(name);
|
error = swapoff(name);
|
||||||
|
|
||||||
if (error == -1) {
|
if (error == -1) {
|
||||||
@ -759,6 +806,8 @@ usage(void)
|
|||||||
fprintf(stderr, "usage: %s ", getprogname());
|
fprintf(stderr, "usage: %s ", getprogname());
|
||||||
switch(orig_prog) {
|
switch(orig_prog) {
|
||||||
case SWAPON:
|
case SWAPON:
|
||||||
|
fprintf(stderr, "[-F fstab] -aLq | [-E] file ...\n");
|
||||||
|
break;
|
||||||
case SWAPOFF:
|
case SWAPOFF:
|
||||||
fprintf(stderr, "[-F fstab] -aLq | file ...\n");
|
fprintf(stderr, "[-F fstab] -aLq | file ...\n");
|
||||||
break;
|
break;
|
||||||
|
@ -216,6 +216,12 @@ then the special file is made available as a piece of swap
|
|||||||
space by the
|
space by the
|
||||||
.Xr swapon 8
|
.Xr swapon 8
|
||||||
command at the end of the system reboot procedure.
|
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,
|
For vnode-backed swap spaces,
|
||||||
.Dq file
|
.Dq file
|
||||||
is supported in the
|
is supported in the
|
||||||
|
Loading…
Reference in New Issue
Block a user