2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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. 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.
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
29 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
30 * @(#)swapon.c 8.1 (Berkeley) 6/5/93
31 * $FreeBSD: src/sbin/swapon/swapon.c,v 1.8.2.2 2001/07/30 10:30:11 dd Exp $
34 #include <sys/param.h>
36 #include <sys/sysctl.h>
37 #include <sys/linker.h>
38 #include <sys/diskslice.h>
39 #include <vm/vm_param.h>
51 #include <bus/cam/scsi/scsi_daio.h>
53 static void usage(void);
54 static int swap_on_off(char *name, int doingall, int trim, int ask);
55 static char *docrypt(char *fs_spec, int pass);
56 static void swaplist(int lflag, int sflag, int hflag);
60 enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
63 main(int argc, char **argv)
69 int doall, sflag, lflag, hflag, eflag, cflag, iflag;
71 if ((ptr = strrchr(argv[0], '/')) == NULL)
73 if (strstr(ptr, "swapon"))
75 else if (strstr(ptr, "swapoff"))
77 orig_prog = which_prog;
79 sflag = lflag = hflag = doall = eflag = cflag = iflag = 0;
80 while ((ch = getopt(argc, argv, "AacdeghiklmqsU")) != -1) {
83 if (which_prog == SWAPCTL) {
91 if (which_prog == SWAPON || which_prog == SWAPOFF)
97 if (which_prog == SWAPCTL)
127 if (which_prog == SWAPON || which_prog == SWAPOFF)
134 if (which_prog == SWAPCTL) {
136 which_prog = SWAPOFF;
149 if (which_prog == SWAPON || which_prog == SWAPOFF) {
151 while ((fsp = getfsent()) != NULL) {
155 if (strcmp(fsp->fs_type, FSTAB_SW))
157 if (strstr(fsp->fs_mntops, "noauto"))
160 if (strstr(fsp->fs_mntops, "notrim"))
162 else if (strstr(fsp->fs_mntops, "trim"))
165 if (cflag || strstr(fsp->fs_mntops, "crypt"))
166 fs_spec = docrypt(fsp->fs_spec, 1);
168 fs_spec = strdup(fsp->fs_spec);
169 if (swap_on_off(fs_spec, 1, dotrim, iflag)) {
173 strstr(fsp->fs_mntops, "crypt")) {
174 docrypt(fsp->fs_spec, 2);
177 printf("%s: %sing %s as swap "
180 (which_prog == SWAPOFF ?
187 } else if (*argv == NULL) {
190 for (; *argv; ++argv) {
191 char *ospec = getdevpath(*argv, 0);
194 fs_spec = docrypt(ospec, 1);
196 fs_spec = strdup(ospec);
197 if (swap_on_off(fs_spec, 0, eflag, iflag)) {
203 printf("%s: %sing %s as swap device\n",
205 (which_prog == SWAPOFF ?
214 swaplist(lflag, sflag, hflag);
223 docrypt(char *fs_spec, int pass)
229 if ((id = strrchr(fs_spec, '/')) == NULL)
233 asprintf(&id, "swap-%s", id);
234 asprintf(&res, "/dev/mapper/%s", id);
240 asprintf(&buf, "/sbin/cryptsetup remove %s", id);
248 if (kldfind("dm_target_crypt") < 0)
249 kldload("dm_target_crypt");
252 "/sbin/cryptsetup --key-file /dev/urandom "
253 "--key-size 256 create %s %s",
262 * NOTE: Don't revert to /dev/da* on error because this could
263 * inadvertently add both /dev/da* and
264 * /dev/mapper/swap-da*.
266 * Allow the swapon operation to report failure or
267 * report a duplicate.
273 res = strdup(fs_spec);
289 trim_volume(char * name)
291 struct partinfo pinfo;
293 size_t bytes = 0,ksize;
299 * Determine if this device is already being used by swap without
302 if ((sysctlbyname("vm.swap_info_array", NULL, &bytes, NULL, 0) < 0) ||
304 err(1, "sysctlbyname()");
307 xswbuf = malloc(bytes);
308 if ((sysctlbyname("vm.swap_info_array", xswbuf, &bytes, NULL, 0) < 0) ||
311 err(1, "sysctlbyname()");
314 ksize = ((struct xswdev *)xswbuf)->xsw_size;
315 n = (int)(bytes / ksize);
316 for (i = 0; i < n; ++i) {
317 xsw = (void *)((char *)xswbuf + i * ksize);
319 if (xsw->xsw_dev == NODEV )
321 if(!strcmp(devname(xsw->xsw_dev, S_IFCHR),
322 name + strlen("/dev/"))) {
323 warnx("%s: device already a swap device", name);
329 * Get the size and offset of this parititon/device
331 fd = open(name, O_RDWR);
333 err(1, "Unable to open %s R+W", name);
334 if (ioctl(fd, DIOCGPART, &pinfo) < 0) {
335 printf("Cannot trim regular file\n");
341 ioarg[0] = pinfo.media_offset;
342 ioarg[1] = pinfo.media_size;
343 printf("Trimming Device:%s, sectors (%llu -%llu)\n",name,
344 (unsigned long long)ioarg[0]/512,
345 (unsigned long long)ioarg[1]/512);
346 if (ioctl(fd, DAIOCTRIM, ioarg) < 0) {
347 printf("Device trim failed\n");
354 swap_on_off(char *name, int doingall, int trim, int ask)
357 if (ask && which_prog == SWAPON) {
358 printf("Do you really want to use device %s as a swap device ?\n", name);
359 printf("You might loose data. [Y/N]");
361 int c = fgetc(stdin);
363 if (c != 'y' && c != 'Y')
367 if (which_prog == SWAPON && trim) {
368 char sysctl_name[64];
369 int trim_enabled = 0;
370 size_t olen = sizeof(trim_enabled);
371 char *dev_name = strdup(name);
372 dev_name = strtok(dev_name + strlen("/dev/da"),"s");
373 sprintf(sysctl_name, "kern.cam.da.%s.trim_enabled", dev_name);
374 if (sysctlbyname(sysctl_name, &trim_enabled, &olen, NULL, 0) < 0) {
376 printf("TRIM not supported on %s, "
381 } else if (!trim_enabled) {
383 printf("TRIM not enabled on %s (%s), "
391 if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) {
395 warnx("%s: device already in use", name);
398 if (which_prog == SWAPON)
399 warnx("%s: NSWAPDEV limit reached", name);
415 fprintf(stderr, "usage: %s ", getprogname());
419 fprintf(stderr, "-aeiq | file ...\n");
422 fprintf(stderr, "[-AeghiklmsU] [-a file ... | -d file ...]\n");
429 sizetobuf(char *buf, size_t bufsize, int hflag, long long val, int hlen,
435 humanize_number(tmp, 5, (int64_t)val, "", HN_AUTOSCALE,
436 HN_B | HN_NOSPACE | HN_DECIMAL);
437 snprintf(buf, bufsize, "%*s", hlen, tmp);
439 snprintf(buf, bufsize, "%*lld", hlen, val / blocksize);
444 swaplist(int lflag, int sflag, int hflag)
446 size_t ksize, bytes = 0;
452 long long total, used, tmp_total, tmp_used;
455 pagesize = getpagesize();
458 blocksize = 1024 * 1024 * 1024;
459 strlcpy(buf, "1GB-blocks", sizeof(buf));
464 strlcpy(buf, "Bytes", sizeof(buf));
469 strlcpy(buf, "1kB-blocks", sizeof(buf));
473 blocksize = 1024 * 1024;
474 strlcpy(buf, "1MB-blocks", sizeof(buf));
478 getbsize(&hlen, &blocksize);
479 snprintf(buf, sizeof(buf), "%ld-blocks", blocksize);
483 if (sysctlbyname("vm.swap_info_array", NULL, &bytes, NULL, 0) < 0)
484 err(1, "sysctlbyname()");
486 err(1, "sysctlbyname()");
488 xswbuf = malloc(bytes);
489 if (sysctlbyname("vm.swap_info_array", xswbuf, &bytes, NULL, 0) < 0) {
491 err(1, "sysctlbyname()");
495 err(1, "sysctlbyname()");
499 * Calculate size of xsw entry returned by kernel (it can be larger
500 * than the one we have if there is a version mismatch).
502 ksize = ((struct xswdev *)xswbuf)->xsw_size;
503 n = (int)(bytes / ksize);
506 printf("%-13s %*s %*s\n",
512 total = used = tmp_total = tmp_used = 0;
513 for (i = 0; i < n; ++i) {
514 xsw = (void *)((char *)xswbuf + i * ksize);
516 if (xsw->xsw_nblks == 0)
519 tmp_total = (long long)xsw->xsw_nblks * pagesize;
520 tmp_used = (long long)xsw->xsw_used * pagesize;
524 sizetobuf(buf, sizeof(buf), hflag, tmp_total, hlen,
526 if (xsw->xsw_dev == NODEV) {
527 printf("%-13s %s ", "[NFS swap]", buf);
529 printf("/dev/%-8s %s ",
530 devname(xsw->xsw_dev, S_IFCHR), buf);
533 sizetobuf(buf, sizeof(buf), hflag, tmp_used, hlen,
540 sizetobuf(buf, sizeof(buf), hflag, total, hlen, blocksize);
541 printf("Total: %s ", buf);
542 sizetobuf(buf, sizeof(buf), hflag, used, hlen, blocksize);