Date: Wed, 18 Dec 2002 15:00:35 -0800 (PST) From: Matthew Dillon <dillon@apollo.backplane.com> To: Matthew Dillon <dillon@apollo.backplane.com> Cc: Eirik Nygaard <eirikn@bluezone.no>, current@FreeBSD.ORG Subject: patch #3 Re: swapoff code comitted. Message-ID: <200212182300.gBIN0ZW7094554@apollo.backplane.com> References: <200212151946.gBFJktmo090730@apollo.backplane.com> <20021215223540.GA601@unixpages.org> <200212152247.gBFMlp4d098705@apollo.backplane.com> <20021218182724.GB853@eirikn.net> <200212181918.gBIJIOIV093115@apollo.backplane.com> <20021218203854.GC853@eirikn.net> <200212182222.gBIMMsnw094344@apollo.backplane.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Here's another update. I cleaned things up even more, add BLOCKSIZE
support, and updated the manual page. It looks quite nice now.
-Matt
Index: Makefile
===================================================================
RCS file: /home/ncvs/src/sbin/swapon/Makefile,v
retrieving revision 1.7
diff -u -r1.7 Makefile
--- Makefile 15 Dec 2002 19:17:56 -0000 1.7
+++ Makefile 18 Dec 2002 21:31:41 -0000
@@ -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>
Index: swapon.8
===================================================================
RCS file: /home/ncvs/src/sbin/swapon/swapon.8,v
retrieving revision 1.21
diff -u -r1.21 swapon.8
--- swapon.8 15 Dec 2002 19:17:56 -0000 1.21
+++ swapon.8 18 Dec 2002 22:46:01 -0000
@@ -43,45 +43,101 @@
.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 sawpped 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
+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 second form is used to configure or disable individual devices.
+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 ,
.Xr init 8 ,
.Xr mdconfig 8 ,
.Xr pstat 8 ,
+.Xr swapinfo 8 ,
.Xr rc 8
.Sh FILES
.Bl -tag -width "/dev/{ad,da}?s?b" -compact
Index: swapon.c
===================================================================
RCS file: /home/ncvs/src/sbin/swapon/swapon.c,v
retrieving revision 1.13
diff -u -r1.13 swapon.c
--- swapon.c 15 Dec 2002 19:17:56 -0000 1.13
+++ swapon.c 18 Dec 2002 22:53:52 -0000
@@ -45,6 +45,11 @@
"$FreeBSD: src/sbin/swapon/swapon.c,v 1.13 2002/12/15 19:17:56 dillon Exp $";
#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,10 +57,13 @@
#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)
@@ -63,48 +71,105 @@
struct fstab *fsp;
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 (strstr(argv[0], "swapon"))
+ which_prog = SWAPON;
+ else if (strstr(argv[0], "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 +185,90 @@
}
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 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);
+ }
}
+
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200212182300.gBIN0ZW7094554>
