summaryrefslogtreecommitdiffstats
path: root/sbin/swapon
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2002-12-28 23:39:47 +0000
committerdillon <dillon@FreeBSD.org>2002-12-28 23:39:47 +0000
commit954749368bc34b7171791be6b1d30aecadb50e11 (patch)
treef87b03e74c9c1e6b9ae164fdbff1e750ba3e8f40 /sbin/swapon
parentf0efa00b3b41ee7113be124c8fcbebe862fb6536 (diff)
downloadFreeBSD-src-954749368bc34b7171791be6b1d30aecadb50e11.zip
FreeBSD-src-954749368bc34b7171791be6b1d30aecadb50e11.tar.gz
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>
Diffstat (limited to 'sbin/swapon')
-rw-r--r--sbin/swapon/Makefile2
-rw-r--r--sbin/swapon/swapon.8101
-rw-r--r--sbin/swapon/swapon.c219
3 files changed, 257 insertions, 65 deletions
diff --git a/sbin/swapon/Makefile b/sbin/swapon/Makefile
index f052567..85b0f0a 100644
--- a/sbin/swapon/Makefile
+++ b/sbin/swapon/Makefile
@@ -4,6 +4,8 @@
PROG= swapon
MAN= swapon.8
LINKS= ${BINDIR}/swapon ${BINDIR}/swapoff
+LINKS+= ${BINDIR}/swapon ${BINDIR}/swapctl
MLINKS= swapon.8 swapoff.8
+MLINKS+=swapon.8 swapctl.8
.include <bsd.prog.mk>
diff --git a/sbin/swapon/swapon.8 b/sbin/swapon/swapon.8
index edda998..cb6cd00 100644
--- a/sbin/swapon/swapon.8
+++ b/sbin/swapon/swapon.8
@@ -43,39 +43,94 @@
.Fl a
.Nm swap[on|off]
.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
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
-utility is used to specify additional devices on which paging and swapping
-are to take place.
-The system begins by swapping and paging on only a single device
-so that only one disk is required at bootstrap time.
-Calls to
-.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.
+utility adds the specified swap devices to the system. If the
+.Fl a
+option is used, all swap devices in
+.Pa /etc/fstab
+will be added, unless their ``noauto'' option is also set.
.Pp
The
.Nm swapoff
-utility disables paging and swapping on a device.
-Calls to
+utility removes the specified swap devices from the system. If the
+.Fl a
+option is used, all swap devices in
+.Pa /etc/fstab
+will be removed, unless their ``noauto'' option is also set.
+Note that
.Nm swapoff
-succeed only if disabling the device would leave enough
-remaining virtual memory to accomodate all running programs.
+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
-Normally, the first form is used:
-.Bl -tag -width indent
-.It Fl a
-All devices marked as ``sw''
-swap devices in
+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
-are added to or removed from the pool of available swap
-unless their ``noauto'' option is also set.
-.El
+which do not have their ``noauto'' option set.
.Pp
-The second form is used to configure or disable individual devices.
+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
.Xr swapon 2 ,
.Xr fstab 5 ,
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index 51042bc..d908b4a 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -45,6 +45,11 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+
#include <err.h>
#include <errno.h>
#include <fstab.h>
@@ -52,59 +57,122 @@ static const char rcsid[] =
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
+
+static void usage(void);
+static int swap_on_off(char *name, int ignoreebusy);
+static void swaplist(int, int, int);
-static void usage(const char *);
-static int is_swapoff(const char *);
-int swap_on_off(char *name, int ignoreebusy, int do_swapoff);
+enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
int
main(int argc, char **argv)
{
struct fstab *fsp;
+ char *ptr;
int stat;
int ch, doall;
- int do_swapoff;
- char *pname = argv[0];
-
- do_swapoff = is_swapoff(pname);
+ int sflag = 0, lflag = 0, hflag = 0;
+ 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;
- while ((ch = getopt(argc, argv, "a")) != -1)
- switch((char)ch) {
+ while ((ch = getopt(argc, argv, "AadlhksU")) != -1) {
+ switch(ch) {
+ case 'A':
+ if (which_prog == SWAPCTL) {
+ doall = 1;
+ which_prog = SWAPON;
+ } else {
+ usage();
+ }
+ break;
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;
case '?':
default:
- usage(pname);
+ usage();
}
+ }
argv += optind;
stat = 0;
- if (doall)
- while ((fsp = getfsent()) != NULL) {
- if (strcmp(fsp->fs_type, FSTAB_SW))
- continue;
- if (strstr(fsp->fs_mntops, "noauto"))
- continue;
- if (swap_on_off(fsp->fs_spec, 1, do_swapoff))
+ if (which_prog == SWAPON || which_prog == SWAPOFF) {
+ if (doall) {
+ while ((fsp = getfsent()) != NULL) {
+ if (strcmp(fsp->fs_type, FSTAB_SW))
+ continue;
+ if (strstr(fsp->fs_mntops, "noauto"))
+ continue;
+ if (swap_on_off(fsp->fs_spec, 0)) {
+ stat = 1;
+ } else {
+ printf("%s: %sing %s as swap device\n",
+ getprogname(), which_prog == SWAPOFF ? "remov" : "add",
+ fsp->fs_spec);
+ }
+ }
+ }
+ else if (!*argv)
+ usage();
+ for (; *argv; ++argv) {
+ if (swap_on_off(*argv, 0)) {
stat = 1;
- else
+ } else if (orig_prog == SWAPCTL) {
printf("%s: %sing %s as swap device\n",
- pname, do_swapoff ? "remov" : "add",
- fsp->fs_spec);
+ getprogname(), which_prog == SWAPOFF ? "remov" : "add",
+ *argv);
+ }
}
- else if (!*argv)
- usage(pname);
- for (; *argv; ++argv)
- stat |= swap_on_off(*argv, 0, do_swapoff);
+ } else {
+ if (lflag || sflag)
+ swaplist(lflag, sflag, hflag);
+ else
+ usage();
+ }
exit(stat);
}
-int
-swap_on_off(char *name, int ignoreebusy, int do_swapoff)
+static int
+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) {
case EBUSY:
if (!ignoreebusy)
@@ -120,23 +188,90 @@ swap_on_off(char *name, int ignoreebusy, int do_swapoff)
}
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);
}
-static int
-is_swapoff(const char *s)
+static void
+swaplist(int lflag, int sflag, int hflag)
{
- const char *u;
-
- if ((u = strrchr(s, '/')) != NULL)
- ++u;
- else
- u = s;
- if (strcmp(u, "swapoff") == 0)
- return 1;
- else
- return 0;
+ 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;
+
+ pagesize = getpagesize();
+ switch(hflag) {
+ case 'K':
+ blocksize = 1024;
+ hlen = 10;
+ break;
+ case 'M':
+ 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);
+ }
}
+
OpenPOWER on IntegriCloud