swapon.c revision 179154
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 179154 2008-05-20 12:24:31Z pjd $"); 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#include <libutil.h> 58 59static void usage(void); 60static int swap_on_off(char *name, int ignoreebusy); 61static void swaplist(int, int, int); 62 63enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; 64 65int 66main(int argc, char **argv) 67{ 68 struct fstab *fsp; 69 char *ptr; 70 int stat; 71 int ch, doall; 72 int sflag = 0, lflag = 0, hflag = 0; 73 74 if ((ptr = strrchr(argv[0], '/')) == NULL) 75 ptr = argv[0]; 76 if (strstr(ptr, "swapon")) 77 which_prog = SWAPON; 78 else if (strstr(ptr, "swapoff")) 79 which_prog = SWAPOFF; 80 orig_prog = which_prog; 81 82 doall = 0; 83 while ((ch = getopt(argc, argv, "AadghklmsU")) != -1) { 84 switch(ch) { 85 case 'A': 86 if (which_prog == SWAPCTL) { 87 doall = 1; 88 which_prog = SWAPON; 89 } else { 90 usage(); 91 } 92 break; 93 case 'a': 94 if (which_prog == SWAPON || which_prog == SWAPOFF) 95 doall = 1; 96 else 97 which_prog = SWAPON; 98 break; 99 case 'd': 100 if (which_prog == SWAPCTL) 101 which_prog = SWAPOFF; 102 else 103 usage(); 104 break; 105 case 'g': 106 hflag = 'G'; 107 break; 108 case 'h': 109 hflag = 'H'; 110 break; 111 case 'k': 112 hflag = 'K'; 113 break; 114 case 'l': 115 lflag = 1; 116 break; 117 case 'm': 118 hflag = 'M'; 119 break; 120 case 's': 121 sflag = 1; 122 break; 123 case 'U': 124 if (which_prog == SWAPCTL) { 125 doall = 1; 126 which_prog = SWAPOFF; 127 } else { 128 usage(); 129 } 130 break; 131 case '?': 132 default: 133 usage(); 134 } 135 } 136 argv += optind; 137 138 stat = 0; 139 if (which_prog == SWAPON || which_prog == SWAPOFF) { 140 if (doall) { 141 while ((fsp = getfsent()) != NULL) { 142 if (strcmp(fsp->fs_type, FSTAB_SW)) 143 continue; 144 if (strstr(fsp->fs_mntops, "noauto")) 145 continue; 146 if (swap_on_off(fsp->fs_spec, 1)) { 147 stat = 1; 148 } else { 149 printf("%s: %sing %s as swap device\n", 150 getprogname(), which_prog == SWAPOFF ? "remov" : "add", 151 fsp->fs_spec); 152 } 153 } 154 } 155 else if (!*argv) 156 usage(); 157 for (; *argv; ++argv) { 158 if (swap_on_off(*argv, 0)) { 159 stat = 1; 160 } else if (orig_prog == SWAPCTL) { 161 printf("%s: %sing %s as swap device\n", 162 getprogname(), which_prog == SWAPOFF ? "remov" : "add", 163 *argv); 164 } 165 } 166 } else { 167 if (lflag || sflag) 168 swaplist(lflag, sflag, hflag); 169 else 170 usage(); 171 } 172 exit(stat); 173} 174 175static int 176swap_on_off(char *name, int doingall) 177{ 178 if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) { 179 switch (errno) { 180 case EBUSY: 181 if (!doingall) 182 warnx("%s: device already in use", name); 183 break; 184 case EINVAL: 185 if (which_prog == SWAPON) 186 warnx("%s: NSWAPDEV limit reached", name); 187 else if (!doingall) 188 warn("%s", name); 189 break; 190 default: 191 warn("%s", name); 192 break; 193 } 194 return(1); 195 } 196 return(0); 197} 198 199static void 200usage(void) 201{ 202 fprintf(stderr, "usage: %s ", getprogname()); 203 switch(orig_prog) { 204 case SWAPON: 205 case SWAPOFF: 206 fprintf(stderr, "-a | file ...\n"); 207 break; 208 case SWAPCTL: 209 fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n"); 210 break; 211 } 212 exit(1); 213} 214 215static void 216sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen, 217 long blocksize) 218{ 219 220 if (hflag == 'H') { 221 char tmp[16]; 222 223 humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE, 224 HN_B | HN_NOSPACE | HN_DECIMAL); 225 snprintf(buf, bufsize, "%*s", hlen, tmp); 226 } else { 227 snprintf(buf, bufsize, "%*lld", hlen, val / blocksize); 228 } 229} 230 231static void 232swaplist(int lflag, int sflag, int hflag) 233{ 234 size_t mibsize, size; 235 struct xswdev xsw; 236 int hlen, mib[16], n, pagesize; 237 long blocksize; 238 long long total = 0; 239 long long used = 0; 240 long long tmp_total; 241 long long tmp_used; 242 char buf[32]; 243 244 pagesize = getpagesize(); 245 switch(hflag) { 246 case 'G': 247 blocksize = 1024 * 1024 * 1024; 248 strlcpy(buf, "1GB-blocks", sizeof(buf)); 249 hlen = 10; 250 break; 251 case 'H': 252 blocksize = -1; 253 strlcpy(buf, "Bytes", sizeof(buf)); 254 hlen = 10; 255 break; 256 case 'K': 257 blocksize = 1024; 258 strlcpy(buf, "1kB-blocks", sizeof(buf)); 259 hlen = 10; 260 break; 261 case 'M': 262 blocksize = 1024 * 1024; 263 strlcpy(buf, "1MB-blocks", sizeof(buf)); 264 hlen = 10; 265 break; 266 default: 267 getbsize(&hlen, &blocksize); 268 snprintf(buf, sizeof(buf), "%ld-blocks", blocksize); 269 break; 270 } 271 272 mibsize = sizeof mib / sizeof mib[0]; 273 if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) 274 err(1, "sysctlnametomib()"); 275 276 if (lflag) { 277 printf("%-13s %*s %*s\n", 278 "Device:", 279 hlen, buf, 280 hlen, "Used:"); 281 } 282 283 for (n = 0; ; ++n) { 284 mib[mibsize] = n; 285 size = sizeof xsw; 286 if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1) 287 break; 288 if (xsw.xsw_version != XSWDEV_VERSION) 289 errx(1, "xswdev version mismatch"); 290 291 tmp_total = (long long)xsw.xsw_nblks * pagesize; 292 tmp_used = (long long)xsw.xsw_used * pagesize; 293 total += tmp_total; 294 used += tmp_used; 295 if (lflag) { 296 sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen, 297 blocksize); 298 printf("/dev/%-8s %s ", devname(xsw.xsw_dev, S_IFCHR), 299 buf); 300 sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen, 301 blocksize); 302 printf("%s\n", buf); 303 } 304 } 305 if (errno != ENOENT) 306 err(1, "sysctl()"); 307 308 if (sflag) { 309 sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize); 310 printf("Total: %s ", buf); 311 sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize); 312 printf("%s\n", buf); 313 } 314} 315 316