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 [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to