Add 'swapctl' - as a hardlink to swapon/swapoff, and augment swapon with
swapctl functionality. The idea is to create a swapctl command that is fairly close to the OpenBSD and NetBSD version. FreeBSD does not implement swap priority (and it would be a mistake if we did) so we didn't bother with that part of it. Submitted by: Eirik Nygaard <eirikn@bluezone.no> Augmented by: dillon (extensively) Reviewed by: David Schultz <dschultz@uclink.Berkeley.EDU>
This commit is contained in:
parent
63100290f3
commit
a420c8119a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=108375
@ -4,6 +4,8 @@
|
|||||||
PROG= swapon
|
PROG= swapon
|
||||||
MAN= swapon.8
|
MAN= swapon.8
|
||||||
LINKS= ${BINDIR}/swapon ${BINDIR}/swapoff
|
LINKS= ${BINDIR}/swapon ${BINDIR}/swapoff
|
||||||
|
LINKS+= ${BINDIR}/swapon ${BINDIR}/swapctl
|
||||||
MLINKS= swapon.8 swapoff.8
|
MLINKS= swapon.8 swapoff.8
|
||||||
|
MLINKS+=swapon.8 swapctl.8
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -43,39 +43,94 @@
|
|||||||
.Fl a
|
.Fl a
|
||||||
.Nm swap[on|off]
|
.Nm swap[on|off]
|
||||||
.Ar special_file ...
|
.Ar special_file ...
|
||||||
|
.Nm swapctl
|
||||||
|
.Fl lshk
|
||||||
|
.Nm swapctl
|
||||||
|
.Fl AU
|
||||||
|
.Nm swapctl
|
||||||
|
.Fl a
|
||||||
|
.Ar special_file ...
|
||||||
|
.Nm swapctl
|
||||||
|
.Fl d
|
||||||
|
.Ar special_file ...
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
|
.Nm swap[on,off,ctl]
|
||||||
|
utilties are used to control swap devices in the system. At boot time all
|
||||||
|
swap entries in
|
||||||
|
.Pa /etc/fstab
|
||||||
|
are added automatically when the system goes multi-user.
|
||||||
|
Swap devices are interleaved and kernels are typically configured
|
||||||
|
to handle a maximum of 4 swap devices. There is no priority mechanism.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
.Nm swapon
|
.Nm swapon
|
||||||
utility is used to specify additional devices on which paging and swapping
|
utility adds the specified swap devices to the system. If the
|
||||||
are to take place.
|
.Fl a
|
||||||
The system begins by swapping and paging on only a single device
|
option is used, all swap devices in
|
||||||
so that only one disk is required at bootstrap time.
|
.Pa /etc/fstab
|
||||||
Calls to
|
will be added, unless their ``noauto'' option is also set.
|
||||||
.Nm swapon
|
|
||||||
normally occur in the system multi-user initialization file
|
|
||||||
.Pa /etc/rc
|
|
||||||
making all swap devices available, so that the paging and swapping
|
|
||||||
activity is interleaved across several devices.
|
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Nm swapoff
|
.Nm swapoff
|
||||||
utility disables paging and swapping on a device.
|
utility removes the specified swap devices from the system. If the
|
||||||
Calls to
|
.Fl a
|
||||||
.Nm swapoff
|
option is used, all swap devices in
|
||||||
succeed only if disabling the device would leave enough
|
|
||||||
remaining virtual memory to accomodate all running programs.
|
|
||||||
.Pp
|
|
||||||
Normally, the first form is used:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Fl a
|
|
||||||
All devices marked as ``sw''
|
|
||||||
swap devices in
|
|
||||||
.Pa /etc/fstab
|
.Pa /etc/fstab
|
||||||
are added to or removed from the pool of available swap
|
will be removed, unless their ``noauto'' option is also set.
|
||||||
unless their ``noauto'' option is also set.
|
Note that
|
||||||
.El
|
.Nm swapoff
|
||||||
|
will fail and refuse to remove a swap device if there is insufficient
|
||||||
|
VM (memory + remaining swap devices) to run the system.
|
||||||
|
.Nm Swapoff
|
||||||
|
must move swapped pages out of the device being removed which could
|
||||||
|
lead to high system loads for a period of time, depending on how
|
||||||
|
much data has been swapped out to that device.
|
||||||
.Pp
|
.Pp
|
||||||
The second form is used to configure or disable individual devices.
|
The
|
||||||
|
.Nm swapctl
|
||||||
|
utility exists primarily for those familiar with other BSDs and may be
|
||||||
|
used to add, remove, or list swap. Note that the
|
||||||
|
.Fl a
|
||||||
|
option is used diferently in
|
||||||
|
.Nm swapctl
|
||||||
|
and indicates that a specific list of devices should be added.
|
||||||
|
The
|
||||||
|
.Fl d
|
||||||
|
option indicates that a specific list should be removed. The
|
||||||
|
.Fl A
|
||||||
|
and
|
||||||
|
.Fl D
|
||||||
|
options to
|
||||||
|
.Nm swapctl
|
||||||
|
operate on all swap entries in
|
||||||
|
.Pa /etc/fstab
|
||||||
|
which do not have their ``noauto'' option set.
|
||||||
|
.Pp
|
||||||
|
Swap information can be generated using the
|
||||||
|
.Nm swapinfo
|
||||||
|
program,
|
||||||
|
.Nm pstat
|
||||||
|
.Fl s ,
|
||||||
|
or
|
||||||
|
.Nm swapctl
|
||||||
|
.Fl lshk .
|
||||||
|
The
|
||||||
|
.Nm swapctl
|
||||||
|
utility has the following options for listing swap:
|
||||||
|
.Bl -tag -width indent
|
||||||
|
.It Fl l
|
||||||
|
List the devices making up system swap.
|
||||||
|
.It Fl s
|
||||||
|
Print a summary line for system swap.
|
||||||
|
.It Fl h
|
||||||
|
Output values in megabytes.
|
||||||
|
.It Fl k
|
||||||
|
Output values in kilobytes.
|
||||||
|
.Pp
|
||||||
|
The BLOCKSIZE environment variable is used if not specifically
|
||||||
|
overridden. 512 byte blocks are used by default.
|
||||||
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr swapon 2 ,
|
.Xr swapon 2 ,
|
||||||
.Xr fstab 5 ,
|
.Xr fstab 5 ,
|
||||||
|
@ -45,6 +45,11 @@ static const char rcsid[] =
|
|||||||
"$FreeBSD$";
|
"$FreeBSD$";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/user.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fstab.h>
|
#include <fstab.h>
|
||||||
@ -52,59 +57,122 @@ static const char rcsid[] =
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
static void usage(const char *);
|
static void usage(void);
|
||||||
static int is_swapoff(const char *);
|
static int swap_on_off(char *name, int ignoreebusy);
|
||||||
int swap_on_off(char *name, int ignoreebusy, int do_swapoff);
|
static void swaplist(int, int, int);
|
||||||
|
|
||||||
|
enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct fstab *fsp;
|
struct fstab *fsp;
|
||||||
|
char *ptr;
|
||||||
int stat;
|
int stat;
|
||||||
int ch, doall;
|
int ch, doall;
|
||||||
int do_swapoff;
|
int sflag = 0, lflag = 0, hflag = 0;
|
||||||
char *pname = argv[0];
|
|
||||||
|
|
||||||
do_swapoff = is_swapoff(pname);
|
if ((ptr = strrchr(argv[0], '/')) == NULL)
|
||||||
|
ptr = argv[0];
|
||||||
|
if (strstr(ptr, "swapon"))
|
||||||
|
which_prog = SWAPON;
|
||||||
|
else if (strstr(ptr, "swapoff"))
|
||||||
|
which_prog = SWAPOFF;
|
||||||
|
orig_prog = which_prog;
|
||||||
|
|
||||||
doall = 0;
|
doall = 0;
|
||||||
while ((ch = getopt(argc, argv, "a")) != -1)
|
while ((ch = getopt(argc, argv, "AadlhksU")) != -1) {
|
||||||
switch((char)ch) {
|
switch(ch) {
|
||||||
|
case 'A':
|
||||||
|
if (which_prog == SWAPCTL) {
|
||||||
|
doall = 1;
|
||||||
|
which_prog = SWAPON;
|
||||||
|
} else {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
doall = 1;
|
if (which_prog == SWAPON || which_prog == SWAPOFF)
|
||||||
|
doall = 1;
|
||||||
|
else
|
||||||
|
which_prog = SWAPON;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (which_prog == SWAPCTL)
|
||||||
|
which_prog = SWAPOFF;
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
sflag = 1;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
lflag = 1;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
hflag = 'M';
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
hflag = 'K';
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
if (which_prog == SWAPCTL) {
|
||||||
|
doall = 1;
|
||||||
|
which_prog = SWAPOFF;
|
||||||
|
} else {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
usage(pname);
|
usage();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
stat = 0;
|
stat = 0;
|
||||||
if (doall)
|
if (which_prog == SWAPON || which_prog == SWAPOFF) {
|
||||||
while ((fsp = getfsent()) != NULL) {
|
if (doall) {
|
||||||
if (strcmp(fsp->fs_type, FSTAB_SW))
|
while ((fsp = getfsent()) != NULL) {
|
||||||
continue;
|
if (strcmp(fsp->fs_type, FSTAB_SW))
|
||||||
if (strstr(fsp->fs_mntops, "noauto"))
|
continue;
|
||||||
continue;
|
if (strstr(fsp->fs_mntops, "noauto"))
|
||||||
if (swap_on_off(fsp->fs_spec, 1, do_swapoff))
|
continue;
|
||||||
stat = 1;
|
if (swap_on_off(fsp->fs_spec, 0)) {
|
||||||
else
|
stat = 1;
|
||||||
printf("%s: %sing %s as swap device\n",
|
} else {
|
||||||
pname, do_swapoff ? "remov" : "add",
|
printf("%s: %sing %s as swap device\n",
|
||||||
fsp->fs_spec);
|
getprogname(), which_prog == SWAPOFF ? "remov" : "add",
|
||||||
|
fsp->fs_spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!*argv)
|
else if (!*argv)
|
||||||
usage(pname);
|
usage();
|
||||||
for (; *argv; ++argv)
|
for (; *argv; ++argv) {
|
||||||
stat |= swap_on_off(*argv, 0, do_swapoff);
|
if (swap_on_off(*argv, 0)) {
|
||||||
|
stat = 1;
|
||||||
|
} else if (orig_prog == SWAPCTL) {
|
||||||
|
printf("%s: %sing %s as swap device\n",
|
||||||
|
getprogname(), which_prog == SWAPOFF ? "remov" : "add",
|
||||||
|
*argv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (lflag || sflag)
|
||||||
|
swaplist(lflag, sflag, hflag);
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
}
|
||||||
exit(stat);
|
exit(stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
swap_on_off(char *name, int ignoreebusy, int do_swapoff)
|
swap_on_off(char *name, int ignoreebusy)
|
||||||
{
|
{
|
||||||
if ((do_swapoff ? swapoff(name) : swapon(name)) == -1) {
|
if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EBUSY:
|
case EBUSY:
|
||||||
if (!ignoreebusy)
|
if (!ignoreebusy)
|
||||||
@ -120,23 +188,90 @@ swap_on_off(char *name, int ignoreebusy, int do_swapoff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(const char *pname)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: %s [-a] [special_file ...]\n", pname);
|
fprintf(stderr, "usage: %s ", getprogname());
|
||||||
|
switch(orig_prog) {
|
||||||
|
case SWAPOFF:
|
||||||
|
fprintf(stderr, "[-a] [special_file ...]\n");
|
||||||
|
break;
|
||||||
|
case SWAPON:
|
||||||
|
fprintf(stderr, "[-a] [special_file ...]\n");
|
||||||
|
break;
|
||||||
|
case SWAPCTL:
|
||||||
|
fprintf(stderr, "[-lshAU] [-a/-d special_file ...]\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
is_swapoff(const char *s)
|
swaplist(int lflag, int sflag, int hflag)
|
||||||
{
|
{
|
||||||
const char *u;
|
size_t mibsize, size;
|
||||||
|
struct xswdev xsw;
|
||||||
|
int mib[16], n, pagesize;
|
||||||
|
size_t hlen;
|
||||||
|
long blocksize;
|
||||||
|
long long total = 0;
|
||||||
|
long long used = 0;
|
||||||
|
long long tmp_total;
|
||||||
|
long long tmp_used;
|
||||||
|
|
||||||
if ((u = strrchr(s, '/')) != NULL)
|
pagesize = getpagesize();
|
||||||
++u;
|
switch(hflag) {
|
||||||
else
|
case 'K':
|
||||||
u = s;
|
blocksize = 1024;
|
||||||
if (strcmp(u, "swapoff") == 0)
|
hlen = 10;
|
||||||
return 1;
|
break;
|
||||||
else
|
case 'M':
|
||||||
return 0;
|
blocksize = 1024 * 1024;
|
||||||
|
hlen = 10;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
getbsize(&hlen, &blocksize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mibsize = sizeof mib / sizeof mib[0];
|
||||||
|
if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1)
|
||||||
|
err(1, "sysctlnametomib()");
|
||||||
|
|
||||||
|
if (lflag) {
|
||||||
|
char buf[32];
|
||||||
|
snprintf(buf, sizeof(buf), "%ld-blocks", blocksize);
|
||||||
|
printf("%-13s %*s %*s\n",
|
||||||
|
"Device:",
|
||||||
|
hlen, buf,
|
||||||
|
hlen, "Used:");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; ; ++n) {
|
||||||
|
mib[mibsize] = n;
|
||||||
|
size = sizeof xsw;
|
||||||
|
if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, NULL) == -1)
|
||||||
|
break;
|
||||||
|
if (xsw.xsw_version != XSWDEV_VERSION)
|
||||||
|
errx(1, "xswdev version mismatch");
|
||||||
|
|
||||||
|
tmp_total = (long long)xsw.xsw_nblks * pagesize / blocksize;
|
||||||
|
tmp_used = (long long)xsw.xsw_used * pagesize / blocksize;
|
||||||
|
total += tmp_total;
|
||||||
|
used += tmp_used;
|
||||||
|
if (lflag) {
|
||||||
|
printf("/dev/%-8s %*lld %*lld\n",
|
||||||
|
devname(xsw.xsw_dev, S_IFCHR),
|
||||||
|
hlen, tmp_total,
|
||||||
|
hlen, tmp_used);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errno != ENOENT)
|
||||||
|
err(1, "sysctl()");
|
||||||
|
|
||||||
|
if (sflag) {
|
||||||
|
printf("Total: %*lld %*lld\n",
|
||||||
|
hlen, total,
|
||||||
|
hlen, used);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user