swapon.c revision 141611
1/*
2 * Copyright (c) 1980, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if 0
31#ifndef lint
32static const char copyright[] =
33"@(#) Copyright (c) 1980, 1993\n\
34	The Regents of the University of California.  All rights reserved.\n";
35#endif /* not lint */
36
37#ifndef lint
38static char sccsid[] = "@(#)swapon.c	8.1 (Berkeley) 6/5/93";
39#endif /* not lint */
40#endif
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/sbin/swapon/swapon.c 141611 2005-02-10 09:19:34Z ru $");
43
44#include <sys/stat.h>
45#include <sys/param.h>
46#include <sys/sysctl.h>
47#include <vm/vm_param.h>
48
49#include <err.h>
50#include <errno.h>
51#include <fstab.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56#include <fcntl.h>
57
58static void usage(void);
59static int swap_on_off(char *name, int ignoreebusy);
60static void swaplist(int, int, int);
61
62enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
63
64int
65main(int argc, char **argv)
66{
67	struct fstab *fsp;
68	char *ptr;
69	int stat;
70	int ch, doall;
71	int sflag = 0, lflag = 0, hflag = 0;
72
73	if ((ptr = strrchr(argv[0], '/')) == NULL)
74		ptr = argv[0];
75	if (strstr(ptr, "swapon"))
76		which_prog = SWAPON;
77	else if (strstr(ptr, "swapoff"))
78		which_prog = SWAPOFF;
79	orig_prog = which_prog;
80
81	doall = 0;
82	while ((ch = getopt(argc, argv, "AadlhksU")) != -1) {
83		switch(ch) {
84		case 'A':
85			if (which_prog == SWAPCTL) {
86				doall = 1;
87				which_prog = SWAPON;
88			} else {
89				usage();
90			}
91			break;
92		case 'a':
93			if (which_prog == SWAPON || which_prog == SWAPOFF)
94				doall = 1;
95			else
96				which_prog = SWAPON;
97			break;
98		case 'd':
99			if (which_prog == SWAPCTL)
100				which_prog = SWAPOFF;
101			else
102				usage();
103			break;
104		case 's':
105			sflag = 1;
106			break;
107		case 'l':
108			lflag = 1;
109			break;
110		case 'h':
111			hflag = 'M';
112			break;
113		case 'k':
114			hflag = 'K';
115			break;
116		case 'U':
117			if (which_prog == SWAPCTL) {
118				doall = 1;
119				which_prog = SWAPOFF;
120			} else {
121				usage();
122			}
123			break;
124		case '?':
125		default:
126			usage();
127		}
128	}
129	argv += optind;
130
131	stat = 0;
132	if (which_prog == SWAPON || which_prog == SWAPOFF) {
133		if (doall) {
134			while ((fsp = getfsent()) != NULL) {
135				if (strcmp(fsp->fs_type, FSTAB_SW))
136					continue;
137				if (strstr(fsp->fs_mntops, "noauto"))
138					continue;
139				if (swap_on_off(fsp->fs_spec, 1)) {
140					stat = 1;
141				} else {
142					printf("%s: %sing %s as swap device\n",
143					    getprogname(), which_prog == SWAPOFF ? "remov" : "add",
144					    fsp->fs_spec);
145				}
146			}
147		}
148		else if (!*argv)
149			usage();
150		for (; *argv; ++argv) {
151			if (swap_on_off(*argv, 0)) {
152				stat = 1;
153			} else if (orig_prog == SWAPCTL) {
154				printf("%s: %sing %s as swap device\n",
155				    getprogname(), which_prog == SWAPOFF ? "remov" : "add",
156				    *argv);
157			}
158		}
159	} else {
160		if (lflag || sflag)
161			swaplist(lflag, sflag, hflag);
162		else
163			usage();
164	}
165	exit(stat);
166}
167
168static int
169swap_on_off(char *name, int doingall)
170{
171	if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) {
172		switch (errno) {
173		case EBUSY:
174			if (!doingall)
175				warnx("%s: device already in use", name);
176			break;
177		case EINVAL:
178			if (which_prog == SWAPON)
179				warnx("%s: NSWAPDEV limit reached", name);
180			else if (!doingall)
181				warn("%s", name);
182			break;
183		default:
184			warn("%s", name);
185			break;
186		}
187		return(1);
188	}
189	return(0);
190}
191
192static void
193usage(void)
194{
195	fprintf(stderr, "usage: %s ", getprogname());
196	switch(orig_prog) {
197	case SWAPON:
198	case SWAPOFF:
199	    fprintf(stderr, "-a | file ...\n");
200	    break;
201	case SWAPCTL:
202	    fprintf(stderr, "[-AhklsU] [-a file ... | -d file ...]\n");
203	    break;
204	}
205	exit(1);
206}
207
208static void
209swaplist(int lflag, int sflag, int hflag)
210{
211	size_t mibsize, size;
212	struct xswdev xsw;
213	int hlen, mib[16], n, pagesize;
214	long blocksize;
215	long long total = 0;
216	long long used = 0;
217	long long tmp_total;
218	long long tmp_used;
219
220	pagesize = getpagesize();
221	switch(hflag) {
222	case 'K':
223	    blocksize = 1024;
224	    hlen = 10;
225	    break;
226	case 'M':
227	    blocksize = 1024 * 1024;
228	    hlen = 10;
229	    break;
230	default:
231	    getbsize(&hlen, &blocksize);
232	    break;
233	}
234
235	mibsize = sizeof mib / sizeof mib[0];
236	if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1)
237		err(1, "sysctlnametomib()");
238
239	if (lflag) {
240		char buf[32];
241		snprintf(buf, sizeof(buf), "%ld-blocks", blocksize);
242		printf("%-13s %*s %*s\n",
243		    "Device:",
244		    hlen, buf,
245		    hlen, "Used:");
246	}
247
248	for (n = 0; ; ++n) {
249		mib[mibsize] = n;
250		size = sizeof xsw;
251		if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1)
252			break;
253		if (xsw.xsw_version != XSWDEV_VERSION)
254			errx(1, "xswdev version mismatch");
255
256		tmp_total = (long long)xsw.xsw_nblks * pagesize / blocksize;
257		tmp_used  = (long long)xsw.xsw_used * pagesize / blocksize;
258		total += tmp_total;
259		used  += tmp_used;
260		if (lflag) {
261			printf("/dev/%-8s %*lld %*lld\n",
262			    devname(xsw.xsw_dev, S_IFCHR),
263			    hlen, tmp_total,
264			    hlen, tmp_used);
265		}
266	}
267	if (errno != ENOENT)
268		err(1, "sysctl()");
269
270	if (sflag) {
271		printf("Total:        %*lld %*lld\n",
272		       hlen, total,
273		       hlen, used);
274	}
275}
276
277