xref: /freebsd/sbin/swapon/swapon.c (revision 45a5dc937d8a1da8c72482cd2c6f776da1290358)
18fae3551SRodney W. Grimes /*
28fae3551SRodney W. Grimes  * Copyright (c) 1980, 1993
38fae3551SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
48fae3551SRodney W. Grimes  *
58fae3551SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
68fae3551SRodney W. Grimes  * modification, are permitted provided that the following conditions
78fae3551SRodney W. Grimes  * are met:
88fae3551SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
98fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
108fae3551SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
118fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
128fae3551SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
138fae3551SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
148fae3551SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
158fae3551SRodney W. Grimes  *    without specific prior written permission.
168fae3551SRodney W. Grimes  *
178fae3551SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
188fae3551SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
198fae3551SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
208fae3551SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
218fae3551SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
228fae3551SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
238fae3551SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
248fae3551SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
258fae3551SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
268fae3551SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
278fae3551SRodney W. Grimes  * SUCH DAMAGE.
288fae3551SRodney W. Grimes  */
298fae3551SRodney W. Grimes 
30c69284caSDavid E. O'Brien #if 0
318fae3551SRodney W. Grimes #ifndef lint
32e798a806SPhilippe Charnier static const char copyright[] =
338fae3551SRodney W. Grimes "@(#) Copyright (c) 1980, 1993\n\
348fae3551SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
358fae3551SRodney W. Grimes #endif /* not lint */
368fae3551SRodney W. Grimes 
378fae3551SRodney W. Grimes #ifndef lint
388fae3551SRodney W. Grimes static char sccsid[] = "@(#)swapon.c	8.1 (Berkeley) 6/5/93";
398fae3551SRodney W. Grimes #endif /* not lint */
40c69284caSDavid E. O'Brien #endif
41c69284caSDavid E. O'Brien #include <sys/cdefs.h>
42c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$");
438fae3551SRodney W. Grimes 
44a420c811SMatthew Dillon #include <sys/stat.h>
45a420c811SMatthew Dillon #include <sys/param.h>
46a420c811SMatthew Dillon #include <sys/sysctl.h>
476004362eSDavid Schultz #include <vm/vm_param.h>
48a420c811SMatthew Dillon 
496da7f378SPhilippe Charnier #include <err.h>
50e798a806SPhilippe Charnier #include <errno.h>
51e798a806SPhilippe Charnier #include <fstab.h>
52e798a806SPhilippe Charnier #include <stdio.h>
53cafefe8cSDima Dorfman #include <stdlib.h>
54e798a806SPhilippe Charnier #include <string.h>
55e798a806SPhilippe Charnier #include <unistd.h>
56a420c811SMatthew Dillon #include <fcntl.h>
572e64768cSPawel Jakub Dawidek #include <libutil.h>
588fae3551SRodney W. Grimes 
59a420c811SMatthew Dillon static void usage(void);
60a420c811SMatthew Dillon static int swap_on_off(char *name, int ignoreebusy);
61a420c811SMatthew Dillon static void swaplist(int, int, int);
62a420c811SMatthew Dillon 
63a420c811SMatthew Dillon enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
6438994f93SPoul-Henning Kamp 
6538994f93SPoul-Henning Kamp int
6638994f93SPoul-Henning Kamp main(int argc, char **argv)
678fae3551SRodney W. Grimes {
683d438ad6SDavid E. O'Brien 	struct fstab *fsp;
69a420c811SMatthew Dillon 	char *ptr;
703d438ad6SDavid E. O'Brien 	int stat;
718fae3551SRodney W. Grimes 	int ch, doall;
7245a5dc93SMike Makonnen 	int sflag = 0, lflag = 0, hflag = 0, qflag = 0;
7392da00bbSMatthew Dillon 
74a420c811SMatthew Dillon 	if ((ptr = strrchr(argv[0], '/')) == NULL)
75a420c811SMatthew Dillon 		ptr = argv[0];
76a420c811SMatthew Dillon 	if (strstr(ptr, "swapon"))
77a420c811SMatthew Dillon 		which_prog = SWAPON;
78a420c811SMatthew Dillon 	else if (strstr(ptr, "swapoff"))
79a420c811SMatthew Dillon 		which_prog = SWAPOFF;
80a420c811SMatthew Dillon 	orig_prog = which_prog;
818fae3551SRodney W. Grimes 
828fae3551SRodney W. Grimes 	doall = 0;
8345a5dc93SMike Makonnen 	while ((ch = getopt(argc, argv, "AadghklmqsU")) != -1) {
84a420c811SMatthew Dillon 		switch(ch) {
85a420c811SMatthew Dillon 		case 'A':
86a420c811SMatthew Dillon 			if (which_prog == SWAPCTL) {
878fae3551SRodney W. Grimes 				doall = 1;
88a420c811SMatthew Dillon 				which_prog = SWAPON;
89a420c811SMatthew Dillon 			} else {
90a420c811SMatthew Dillon 				usage();
91a420c811SMatthew Dillon 			}
92a420c811SMatthew Dillon 			break;
93a420c811SMatthew Dillon 		case 'a':
94a420c811SMatthew Dillon 			if (which_prog == SWAPON || which_prog == SWAPOFF)
95a420c811SMatthew Dillon 				doall = 1;
96a420c811SMatthew Dillon 			else
97a420c811SMatthew Dillon 				which_prog = SWAPON;
98a420c811SMatthew Dillon 			break;
99a420c811SMatthew Dillon 		case 'd':
100a420c811SMatthew Dillon 			if (which_prog == SWAPCTL)
101a420c811SMatthew Dillon 				which_prog = SWAPOFF;
102a420c811SMatthew Dillon 			else
103a420c811SMatthew Dillon 				usage();
104a420c811SMatthew Dillon 			break;
1052e64768cSPawel Jakub Dawidek 		case 'g':
1062e64768cSPawel Jakub Dawidek 			hflag = 'G';
1072e64768cSPawel Jakub Dawidek 			break;
1082e64768cSPawel Jakub Dawidek 		case 'h':
1092e64768cSPawel Jakub Dawidek 			hflag = 'H';
1102e64768cSPawel Jakub Dawidek 			break;
1112e64768cSPawel Jakub Dawidek 		case 'k':
1122e64768cSPawel Jakub Dawidek 			hflag = 'K';
113a420c811SMatthew Dillon 			break;
114a420c811SMatthew Dillon 		case 'l':
115a420c811SMatthew Dillon 			lflag = 1;
116a420c811SMatthew Dillon 			break;
1172e64768cSPawel Jakub Dawidek 		case 'm':
118a420c811SMatthew Dillon 			hflag = 'M';
119a420c811SMatthew Dillon 			break;
12045a5dc93SMike Makonnen 		case 'q':
12145a5dc93SMike Makonnen 			if (which_prog == SWAPON || which_prog == SWAPOFF)
12245a5dc93SMike Makonnen 				qflag = 1;
12345a5dc93SMike Makonnen 			break;
1242e64768cSPawel Jakub Dawidek 		case 's':
1252e64768cSPawel Jakub Dawidek 			sflag = 1;
126a420c811SMatthew Dillon 			break;
127a420c811SMatthew Dillon 		case 'U':
128a420c811SMatthew Dillon 			if (which_prog == SWAPCTL) {
129a420c811SMatthew Dillon 				doall = 1;
130a420c811SMatthew Dillon 				which_prog = SWAPOFF;
131a420c811SMatthew Dillon 			} else {
132a420c811SMatthew Dillon 				usage();
133a420c811SMatthew Dillon 			}
1348fae3551SRodney W. Grimes 			break;
1358fae3551SRodney W. Grimes 		case '?':
1368fae3551SRodney W. Grimes 		default:
137a420c811SMatthew Dillon 			usage();
138a420c811SMatthew Dillon 		}
1398fae3551SRodney W. Grimes 	}
1408fae3551SRodney W. Grimes 	argv += optind;
1418fae3551SRodney W. Grimes 
1428fae3551SRodney W. Grimes 	stat = 0;
143a420c811SMatthew Dillon 	if (which_prog == SWAPON || which_prog == SWAPOFF) {
144a420c811SMatthew Dillon 		if (doall) {
14538994f93SPoul-Henning Kamp 			while ((fsp = getfsent()) != NULL) {
1468fae3551SRodney W. Grimes 				if (strcmp(fsp->fs_type, FSTAB_SW))
1478fae3551SRodney W. Grimes 					continue;
1487fc4a454SJordan K. Hubbard 				if (strstr(fsp->fs_mntops, "noauto"))
1497fc4a454SJordan K. Hubbard 					continue;
1504937798dSDavid Schultz 				if (swap_on_off(fsp->fs_spec, 1)) {
1518fae3551SRodney W. Grimes 					stat = 1;
152a420c811SMatthew Dillon 				} else {
15345a5dc93SMike Makonnen 					if (!qflag) {
15492da00bbSMatthew Dillon 						printf("%s: %sing %s as swap device\n",
15545a5dc93SMike Makonnen 						    getprogname(),
15645a5dc93SMike Makonnen 						    which_prog == SWAPOFF ? "remov" : "add",
1578fae3551SRodney W. Grimes 						    fsp->fs_spec);
1588fae3551SRodney W. Grimes 					}
159a420c811SMatthew Dillon 				}
160a420c811SMatthew Dillon 			}
16145a5dc93SMike Makonnen 		}
1628fae3551SRodney W. Grimes 		else if (!*argv)
163a420c811SMatthew Dillon 			usage();
164a420c811SMatthew Dillon 		for (; *argv; ++argv) {
165a420c811SMatthew Dillon 			if (swap_on_off(*argv, 0)) {
166a420c811SMatthew Dillon 				stat = 1;
167a420c811SMatthew Dillon 			} else if (orig_prog == SWAPCTL) {
168a420c811SMatthew Dillon 				printf("%s: %sing %s as swap device\n",
169a420c811SMatthew Dillon 				    getprogname(), which_prog == SWAPOFF ? "remov" : "add",
170a420c811SMatthew Dillon 				    *argv);
171a420c811SMatthew Dillon 			}
172a420c811SMatthew Dillon 		}
173a420c811SMatthew Dillon 	} else {
174a420c811SMatthew Dillon 		if (lflag || sflag)
175a420c811SMatthew Dillon 			swaplist(lflag, sflag, hflag);
176a420c811SMatthew Dillon 		else
177a420c811SMatthew Dillon 			usage();
178a420c811SMatthew Dillon 	}
1798fae3551SRodney W. Grimes 	exit(stat);
1808fae3551SRodney W. Grimes }
1818fae3551SRodney W. Grimes 
182a420c811SMatthew Dillon static int
1834937798dSDavid Schultz swap_on_off(char *name, int doingall)
1848fae3551SRodney W. Grimes {
185a420c811SMatthew Dillon 	if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) {
1868fae3551SRodney W. Grimes 		switch (errno) {
1878fae3551SRodney W. Grimes 		case EBUSY:
1884937798dSDavid Schultz 			if (!doingall)
1896da7f378SPhilippe Charnier 				warnx("%s: device already in use", name);
1908fae3551SRodney W. Grimes 			break;
1914937798dSDavid Schultz 		case EINVAL:
1924937798dSDavid Schultz 			if (which_prog == SWAPON)
1934937798dSDavid Schultz 				warnx("%s: NSWAPDEV limit reached", name);
1944937798dSDavid Schultz 			else if (!doingall)
1954937798dSDavid Schultz 				warn("%s", name);
1964937798dSDavid Schultz 			break;
1978fae3551SRodney W. Grimes 		default:
1986da7f378SPhilippe Charnier 			warn("%s", name);
1998fae3551SRodney W. Grimes 			break;
2008fae3551SRodney W. Grimes 		}
2018fae3551SRodney W. Grimes 		return(1);
2028fae3551SRodney W. Grimes 	}
2038fae3551SRodney W. Grimes 	return(0);
2048fae3551SRodney W. Grimes }
2058fae3551SRodney W. Grimes 
2066da7f378SPhilippe Charnier static void
207a420c811SMatthew Dillon usage(void)
2088fae3551SRodney W. Grimes {
209a420c811SMatthew Dillon 	fprintf(stderr, "usage: %s ", getprogname());
210a420c811SMatthew Dillon 	switch(orig_prog) {
211a420c811SMatthew Dillon 	case SWAPON:
2128d646af5SRuslan Ermilov 	case SWAPOFF:
21345a5dc93SMike Makonnen 	    fprintf(stderr, "-aq | file ...\n");
214a420c811SMatthew Dillon 	    break;
215a420c811SMatthew Dillon 	case SWAPCTL:
2162e64768cSPawel Jakub Dawidek 	    fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n");
217a420c811SMatthew Dillon 	    break;
218a420c811SMatthew Dillon 	}
2198fae3551SRodney W. Grimes 	exit(1);
2208fae3551SRodney W. Grimes }
22192da00bbSMatthew Dillon 
222a420c811SMatthew Dillon static void
2232e64768cSPawel Jakub Dawidek sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen,
2242e64768cSPawel Jakub Dawidek     long blocksize)
2252e64768cSPawel Jakub Dawidek {
2262e64768cSPawel Jakub Dawidek 
2272e64768cSPawel Jakub Dawidek 	if (hflag == 'H') {
2282e64768cSPawel Jakub Dawidek 		char tmp[16];
2292e64768cSPawel Jakub Dawidek 
2302e64768cSPawel Jakub Dawidek 		humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE,
2312e64768cSPawel Jakub Dawidek 		    HN_B | HN_NOSPACE | HN_DECIMAL);
2322e64768cSPawel Jakub Dawidek 		snprintf(buf, bufsize, "%*s", hlen, tmp);
2332e64768cSPawel Jakub Dawidek 	} else {
2342e64768cSPawel Jakub Dawidek 		snprintf(buf, bufsize, "%*lld", hlen, val / blocksize);
2352e64768cSPawel Jakub Dawidek 	}
2362e64768cSPawel Jakub Dawidek }
2372e64768cSPawel Jakub Dawidek 
2382e64768cSPawel Jakub Dawidek static void
239a420c811SMatthew Dillon swaplist(int lflag, int sflag, int hflag)
24092da00bbSMatthew Dillon {
241a420c811SMatthew Dillon 	size_t mibsize, size;
242a420c811SMatthew Dillon 	struct xswdev xsw;
24369095b02SMike Barcroft 	int hlen, mib[16], n, pagesize;
244a420c811SMatthew Dillon 	long blocksize;
245a420c811SMatthew Dillon 	long long total = 0;
246a420c811SMatthew Dillon 	long long used = 0;
247a420c811SMatthew Dillon 	long long tmp_total;
248a420c811SMatthew Dillon 	long long tmp_used;
2492e64768cSPawel Jakub Dawidek 	char buf[32];
25092da00bbSMatthew Dillon 
251a420c811SMatthew Dillon 	pagesize = getpagesize();
252a420c811SMatthew Dillon 	switch(hflag) {
2532e64768cSPawel Jakub Dawidek 	case 'G':
2542e64768cSPawel Jakub Dawidek 	    blocksize = 1024 * 1024 * 1024;
2552e64768cSPawel Jakub Dawidek 	    strlcpy(buf, "1GB-blocks", sizeof(buf));
2562e64768cSPawel Jakub Dawidek 	    hlen = 10;
2572e64768cSPawel Jakub Dawidek 	    break;
2582e64768cSPawel Jakub Dawidek 	case 'H':
2592e64768cSPawel Jakub Dawidek 	    blocksize = -1;
2602e64768cSPawel Jakub Dawidek 	    strlcpy(buf, "Bytes", sizeof(buf));
2612e64768cSPawel Jakub Dawidek 	    hlen = 10;
2622e64768cSPawel Jakub Dawidek 	    break;
263a420c811SMatthew Dillon 	case 'K':
264a420c811SMatthew Dillon 	    blocksize = 1024;
2652e64768cSPawel Jakub Dawidek 	    strlcpy(buf, "1kB-blocks", sizeof(buf));
266a420c811SMatthew Dillon 	    hlen = 10;
267a420c811SMatthew Dillon 	    break;
268a420c811SMatthew Dillon 	case 'M':
269a420c811SMatthew Dillon 	    blocksize = 1024 * 1024;
2702e64768cSPawel Jakub Dawidek 	    strlcpy(buf, "1MB-blocks", sizeof(buf));
271a420c811SMatthew Dillon 	    hlen = 10;
272a420c811SMatthew Dillon 	    break;
273a420c811SMatthew Dillon 	default:
2749255f327SMike Barcroft 	    getbsize(&hlen, &blocksize);
2752e64768cSPawel Jakub Dawidek 	    snprintf(buf, sizeof(buf), "%ld-blocks", blocksize);
276a420c811SMatthew Dillon 	    break;
27792da00bbSMatthew Dillon 	}
278a420c811SMatthew Dillon 
279a420c811SMatthew Dillon 	mibsize = sizeof mib / sizeof mib[0];
280a420c811SMatthew Dillon 	if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1)
281a420c811SMatthew Dillon 		err(1, "sysctlnametomib()");
282a420c811SMatthew Dillon 
283a420c811SMatthew Dillon 	if (lflag) {
284a420c811SMatthew Dillon 		printf("%-13s %*s %*s\n",
285a420c811SMatthew Dillon 		    "Device:",
286a420c811SMatthew Dillon 		    hlen, buf,
287a420c811SMatthew Dillon 		    hlen, "Used:");
288a420c811SMatthew Dillon 	}
289a420c811SMatthew Dillon 
290a420c811SMatthew Dillon 	for (n = 0; ; ++n) {
291a420c811SMatthew Dillon 		mib[mibsize] = n;
292a420c811SMatthew Dillon 		size = sizeof xsw;
29316fc3635SMark Murray 		if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1)
294a420c811SMatthew Dillon 			break;
295a420c811SMatthew Dillon 		if (xsw.xsw_version != XSWDEV_VERSION)
296a420c811SMatthew Dillon 			errx(1, "xswdev version mismatch");
297a420c811SMatthew Dillon 
2982e64768cSPawel Jakub Dawidek 		tmp_total = (long long)xsw.xsw_nblks * pagesize;
2992e64768cSPawel Jakub Dawidek 		tmp_used  = (long long)xsw.xsw_used * pagesize;
300a420c811SMatthew Dillon 		total += tmp_total;
301a420c811SMatthew Dillon 		used  += tmp_used;
302a420c811SMatthew Dillon 		if (lflag) {
3032e64768cSPawel Jakub Dawidek 			sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen,
3042e64768cSPawel Jakub Dawidek 			    blocksize);
3052e64768cSPawel Jakub Dawidek 			printf("/dev/%-8s %s ", devname(xsw.xsw_dev, S_IFCHR),
3062e64768cSPawel Jakub Dawidek 			    buf);
3072e64768cSPawel Jakub Dawidek 			sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen,
3082e64768cSPawel Jakub Dawidek 			    blocksize);
3092e64768cSPawel Jakub Dawidek 			printf("%s\n", buf);
310a420c811SMatthew Dillon 		}
311a420c811SMatthew Dillon 	}
312a420c811SMatthew Dillon 	if (errno != ENOENT)
313a420c811SMatthew Dillon 		err(1, "sysctl()");
314a420c811SMatthew Dillon 
315a420c811SMatthew Dillon 	if (sflag) {
3162e64768cSPawel Jakub Dawidek 		sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize);
3172e64768cSPawel Jakub Dawidek 		printf("Total:        %s ", buf);
3182e64768cSPawel Jakub Dawidek 		sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize);
3192e64768cSPawel Jakub Dawidek 		printf("%s\n", buf);
320a420c811SMatthew Dillon 	}
321a420c811SMatthew Dillon }
322a420c811SMatthew Dillon 
323