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 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved. 34 * @(#)swapon.c 8.1 (Berkeley) 6/5/93 35 * $FreeBSD: src/sbin/swapon/swapon.c,v 1.8.2.2 2001/07/30 10:30:11 dd Exp $ 36 * $DragonFly: src/sbin/swapon/swapon.c,v 1.5 2005/11/06 12:50:21 swildner Exp $ 37 */ 38 39 #include <sys/param.h> 40 #include <sys/stat.h> 41 #include <sys/sysctl.h> 42 #include <vm/vm_param.h> 43 44 #include <err.h> 45 #include <errno.h> 46 #include <fstab.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 #include <fcntl.h> 52 #include <libutil.h> 53 54 static void usage(void); 55 static int swap_on_off(char *name, int doingall); 56 static void swaplist(int lflag, int sflag, int hflag); 57 58 enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; 59 60 int 61 main(int argc, char **argv) 62 { 63 struct fstab *fsp; 64 char *ptr; 65 int ret; 66 int ch; 67 int doall, sflag, lflag, hflag, qflag; 68 69 if ((ptr = strrchr(argv[0], '/')) == NULL) 70 ptr = argv[0]; 71 if (strstr(ptr, "swapon")) 72 which_prog = SWAPON; 73 else if (strstr(ptr, "swapoff")) 74 which_prog = SWAPOFF; 75 orig_prog = which_prog; 76 77 sflag = lflag = hflag = qflag = doall = 0; 78 while ((ch = getopt(argc, argv, "AadghklmqsU")) != -1) { 79 switch((char)ch) { 80 case 'A': 81 if (which_prog == SWAPCTL) { 82 doall = 1; 83 which_prog = SWAPON; 84 } else { 85 usage(); 86 } 87 break; 88 case 'a': 89 if (which_prog == SWAPON || which_prog == SWAPOFF) 90 doall = 1; 91 else 92 which_prog = SWAPON; 93 break; 94 case 'd': 95 if (which_prog == SWAPCTL) 96 which_prog = SWAPOFF; 97 else 98 usage(); 99 break; 100 case 'g': 101 hflag = 'G'; 102 break; 103 case 'h': 104 hflag = 'H'; 105 break; 106 case 'k': 107 hflag = 'K'; 108 break; 109 case 'l': 110 lflag = 1; 111 break; 112 case 'm': 113 hflag = 'M'; 114 break; 115 case 'q': 116 if (which_prog == SWAPON || which_prog == SWAPOFF) 117 qflag = 1; 118 break; 119 case 's': 120 sflag = 1; 121 break; 122 case 'U': 123 if (which_prog == SWAPCTL) { 124 doall = 1; 125 which_prog = SWAPOFF; 126 } else { 127 usage(); 128 } 129 break; 130 case '?': 131 default: 132 usage(); 133 } 134 } 135 argv += optind; 136 137 ret = 0; 138 if (which_prog == SWAPON || which_prog == SWAPOFF) { 139 if (doall) { 140 while ((fsp = getfsent()) != NULL) { 141 if (strcmp(fsp->fs_type, FSTAB_SW)) 142 continue; 143 if (strstr(fsp->fs_mntops, "noauto")) 144 continue; 145 if (swap_on_off(fsp->fs_spec, 1)) { 146 ret = 1; 147 } else { 148 if (!qflag) { 149 printf("%s: %sing %s as swap device\n", 150 getprogname(), 151 which_prog == SWAPOFF ? "remov" : "add", 152 fsp->fs_spec); 153 } 154 } 155 } 156 } else if (*argv == NULL) { 157 usage(); 158 } 159 for (; *argv; ++argv) { 160 if (swap_on_off(getdevpath(*argv, 0), 0)) { 161 ret = 1; 162 } else if (orig_prog == SWAPCTL) { 163 printf("%s: %sing %s as swap device\n", 164 getprogname(), 165 which_prog == SWAPOFF ? "remov" : "add", 166 *argv); 167 } 168 } 169 } else { 170 if (lflag || sflag) 171 swaplist(lflag, sflag, hflag); 172 else 173 usage(); 174 } 175 exit(ret); 176 } 177 178 static int 179 swap_on_off(char *name, int doingall) 180 { 181 if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) { 182 switch(errno) { 183 case EBUSY: 184 if (!doingall) 185 warnx("%s: device already in use", name); 186 break; 187 case EINVAL: 188 if (which_prog == SWAPON) 189 warnx("%s: NSWAPDEV limit reached", name); 190 else if (!doingall) 191 warn("%s", name); 192 break; 193 default: 194 warn("%s", name); 195 break; 196 } 197 return(1); 198 } 199 return(0); 200 } 201 202 static void 203 usage(void) 204 { 205 fprintf(stderr, "usage: %s ", getprogname()); 206 switch (orig_prog) { 207 case SWAPON: 208 case SWAPOFF: 209 fprintf(stderr, "-aq | file ...\n"); 210 break; 211 case SWAPCTL: 212 fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n"); 213 break; 214 } 215 exit(1); 216 } 217 218 static void 219 sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen, 220 long blocksize) 221 { 222 if (hflag == 'H') { 223 char tmp[16]; 224 225 humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE, 226 HN_B | HN_NOSPACE | HN_DECIMAL); 227 snprintf(buf, bufsize, "%*s", hlen, tmp); 228 } else { 229 snprintf(buf, bufsize, "%*lld", hlen, val / blocksize); 230 } 231 } 232 233 static void 234 swaplist(int lflag, int sflag, int hflag) 235 { 236 size_t ksize, bytes = 0; 237 char *xswbuf; 238 struct xswdev *xsw; 239 int hlen, pagesize; 240 int i, n; 241 long blocksize; 242 long long total, used, tmp_total, tmp_used; 243 char buf[32]; 244 245 pagesize = getpagesize(); 246 switch(hflag) { 247 case 'G': 248 blocksize = 1024 * 1024 * 1024; 249 strlcpy(buf, "1GB-blocks", sizeof(buf)); 250 hlen = 10; 251 break; 252 case 'H': 253 blocksize = -1; 254 strlcpy(buf, "Bytes", sizeof(buf)); 255 hlen = 10; 256 break; 257 case 'K': 258 blocksize = 1024; 259 strlcpy(buf, "1kB-blocks", sizeof(buf)); 260 hlen = 10; 261 break; 262 case 'M': 263 blocksize = 1024 * 1024; 264 strlcpy(buf, "1MB-blocks", sizeof(buf)); 265 hlen = 10; 266 break; 267 default: 268 getbsize(&hlen, &blocksize); 269 snprintf(buf, sizeof(buf), "%ld-blocks", blocksize); 270 break; 271 } 272 273 if (sysctlbyname("vm.swap_info_array", NULL, &bytes, NULL, 0) < 0) 274 err(1, "sysctlbyname()"); 275 if (bytes == 0) 276 err(1, "sysctlbyname()"); 277 278 xswbuf = malloc(bytes); 279 if (sysctlbyname("vm.swap_info_array", xswbuf, &bytes, NULL, 0) < 0) { 280 free(xswbuf); 281 err(1, "sysctlbyname()"); 282 } 283 if (bytes == 0) { 284 free(xswbuf); 285 err(1, "sysctlbyname()"); 286 } 287 288 /* 289 * Calculate size of xsw entry returned by kernel (it can be larger 290 * than the one we have if there is a version mismatch). 291 */ 292 ksize = ((struct xswdev *)xswbuf)->xsw_size; 293 n = (int)(bytes / ksize); 294 295 if (lflag) { 296 printf("%-13s %*s %*s\n", 297 "Device:", 298 hlen, buf, 299 hlen, "Used:"); 300 } 301 302 total = used = tmp_total = tmp_used = 0; 303 for (i = 0; i < n; ++i) { 304 xsw = (void *)((char *)xswbuf + i * ksize); 305 306 if (xsw->xsw_nblks == 0) 307 continue; 308 309 if (sflag) { 310 tmp_total = (long long)xsw->xsw_nblks * pagesize; 311 tmp_used = (long long)xsw->xsw_used * pagesize; 312 total += tmp_total; 313 used += tmp_used; 314 } 315 316 if (lflag) { 317 sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen, 318 blocksize); 319 if (xsw->xsw_dev == NODEV) { 320 printf("%-13s %s ", "[NFS swap]", buf); 321 } else { 322 printf("/dev/%-8s %s ", 323 devname(xsw->xsw_dev, S_IFCHR), buf); 324 } 325 326 sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen, 327 blocksize); 328 printf("%s\n", buf); 329 } 330 } 331 332 if (sflag) { 333 sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize); 334 printf("Total: %s ", buf); 335 sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize); 336 printf("%s\n", buf); 337 } 338 } 339