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 <sys/ioctl_compat.h>
40 #include <vm/vm_param.h>
52 static void usage(void);
53 static int swap_on_off(char *name
, int doingall
, int trim
, int ask
);
54 static char *docrypt(char *fs_spec
, int pass
);
55 static void swaplist(int lflag
, int sflag
, int hflag
);
59 enum { SWAPON
, SWAPOFF
, SWAPCTL
} orig_prog
, which_prog
= SWAPCTL
;
62 main(int argc
, char **argv
)
68 int doall
, sflag
, lflag
, hflag
, eflag
, cflag
, iflag
;
70 if ((ptr
= strrchr(argv
[0], '/')) == NULL
)
72 if (strstr(ptr
, "swapon"))
74 else if (strstr(ptr
, "swapoff"))
76 orig_prog
= which_prog
;
78 sflag
= lflag
= hflag
= doall
= eflag
= cflag
= iflag
= 0;
79 while ((ch
= getopt(argc
, argv
, "AacdeghiklmqsU")) != -1) {
82 if (which_prog
== SWAPCTL
) {
90 if (which_prog
== SWAPON
|| which_prog
== SWAPOFF
)
96 if (which_prog
== SWAPCTL
)
126 if (which_prog
== SWAPON
|| which_prog
== SWAPOFF
)
133 if (which_prog
== SWAPCTL
) {
135 which_prog
= SWAPOFF
;
148 if (which_prog
== SWAPON
|| which_prog
== SWAPOFF
) {
150 while ((fsp
= getfsent()) != NULL
) {
154 if (strcmp(fsp
->fs_type
, FSTAB_SW
))
156 if (strstr(fsp
->fs_mntops
, "noauto"))
159 if (strstr(fsp
->fs_mntops
, "notrim"))
161 else if (strstr(fsp
->fs_mntops
, "trim"))
164 if (cflag
|| strstr(fsp
->fs_mntops
, "crypt"))
165 fs_spec
= docrypt(fsp
->fs_spec
, 1);
167 fs_spec
= strdup(fsp
->fs_spec
);
168 if (swap_on_off(fs_spec
, 1, dotrim
, iflag
)) {
172 strstr(fsp
->fs_mntops
, "crypt")) {
173 docrypt(fsp
->fs_spec
, 2);
176 printf("%s: %sing %s as swap "
179 (which_prog
== SWAPOFF
?
186 } else if (*argv
== NULL
) {
189 for (; *argv
; ++argv
) {
190 char *ospec
= getdevpath(*argv
, 0);
193 fs_spec
= docrypt(ospec
, 1);
195 fs_spec
= strdup(ospec
);
196 if (swap_on_off(fs_spec
, 0, eflag
, iflag
)) {
202 printf("%s: %sing %s as swap device\n",
204 (which_prog
== SWAPOFF
?
213 swaplist(lflag
, sflag
, hflag
);
222 docrypt(char *fs_spec
, int pass
)
228 if ((id
= strrchr(fs_spec
, '/')) == NULL
)
232 asprintf(&id
, "swap-%s", id
);
233 asprintf(&res
, "/dev/mapper/%s", id
);
239 asprintf(&buf
, "/sbin/cryptsetup remove %s", id
);
247 if (kldfind("dm_target_crypt") < 0)
248 kldload("dm_target_crypt");
251 "/sbin/cryptsetup --key-file /dev/urandom "
252 "--key-size 256 create %s %s",
261 * NOTE: Don't revert to /dev/da* on error because this could
262 * inadvertently add both /dev/da* and
263 * /dev/mapper/swap-da*.
265 * Allow the swapon operation to report failure or
266 * report a duplicate.
272 res
= strdup(fs_spec
);
288 trim_volume(char * name
)
290 struct partinfo pinfo
;
292 size_t bytes
= 0,ksize
;
298 * Determine if this device is already being used by swap without
301 if ((sysctlbyname("vm.swap_info_array", NULL
, &bytes
, NULL
, 0) < 0) ||
303 err(1, "sysctlbyname()");
306 xswbuf
= malloc(bytes
);
307 if ((sysctlbyname("vm.swap_info_array", xswbuf
, &bytes
, NULL
, 0) < 0) ||
310 err(1, "sysctlbyname()");
313 ksize
= ((struct xswdev
*)xswbuf
)->xsw_size
;
314 n
= (int)(bytes
/ ksize
);
315 for (i
= 0; i
< n
; ++i
) {
316 xsw
= (void *)((char *)xswbuf
+ i
* ksize
);
318 if (xsw
->xsw_dev
== NODEV
)
320 if(!strcmp(devname(xsw
->xsw_dev
, S_IFCHR
),
321 name
+ strlen("/dev/"))) {
322 warnx("%s: device already a swap device", name
);
328 * Get the size and offset of this parititon/device
330 fd
= open(name
, O_RDWR
);
332 err(1, "Unable to open %s R+W", name
);
333 if (ioctl(fd
, DIOCGPART
, &pinfo
) < 0) {
334 printf("Cannot trim regular file\n");
340 ioarg
[0] = pinfo
.media_offset
;
341 ioarg
[1] = pinfo
.media_size
;
342 printf("Trimming Device:%s, sectors (%llu -%llu)\n",name
,
343 (unsigned long long)ioarg
[0]/512,
344 (unsigned long long)ioarg
[1]/512);
345 if (ioctl(fd
, IOCTLTRIM
, ioarg
) < 0) {
346 printf("Device trim failed\n");
353 swap_on_off(char *name
, int doingall
, int trim
, int ask
)
356 if (ask
&& which_prog
== SWAPON
) {
357 printf("Do you really want to use device %s as a swap device ?\n", name
);
358 printf("You might loose data. [Y/N]");
360 int c
= fgetc(stdin
);
362 if (c
!= 'y' && c
!= 'Y')
366 if (which_prog
== SWAPON
&& trim
) {
367 char sysctl_name
[64];
368 int trim_enabled
= 0;
369 size_t olen
= sizeof(trim_enabled
);
370 char *dev_name
= strdup(name
);
371 dev_name
= strtok(dev_name
+ strlen("/dev/da"),"s");
372 sprintf(sysctl_name
, "kern.cam.da.%s.trim_enabled", dev_name
);
373 if (sysctlbyname(sysctl_name
, &trim_enabled
, &olen
, NULL
, 0) < 0) {
375 printf("TRIM not supported on %s, "
380 } else if (!trim_enabled
) {
382 printf("TRIM not enabled on %s (%s), "
390 if ((which_prog
== SWAPOFF
? swapoff(name
) : swapon(name
)) == -1) {
394 warnx("%s: device already in use", name
);
397 if (which_prog
== SWAPON
)
398 warnx("%s: NSWAPDEV limit reached", name
);
414 fprintf(stderr
, "usage: %s ", getprogname());
418 fprintf(stderr
, "-aeiq | file ...\n");
421 fprintf(stderr
, "[-AeghiklmsU] [-a file ... | -d file ...]\n");
428 sizetobuf(char *buf
, size_t bufsize
, int hflag
, long long val
, int hlen
,
434 humanize_number(tmp
, 5, (int64_t)val
, "", HN_AUTOSCALE
,
435 HN_B
| HN_NOSPACE
| HN_DECIMAL
);
436 snprintf(buf
, bufsize
, "%*s", hlen
, tmp
);
438 snprintf(buf
, bufsize
, "%*lld", hlen
, val
/ blocksize
);
443 swaplist(int lflag
, int sflag
, int hflag
)
445 size_t ksize
, bytes
= 0;
451 long long total
, used
, tmp_total
, tmp_used
;
454 pagesize
= getpagesize();
457 blocksize
= 1024 * 1024 * 1024;
458 strlcpy(buf
, "1GB-blocks", sizeof(buf
));
463 strlcpy(buf
, "Bytes", sizeof(buf
));
468 strlcpy(buf
, "1kB-blocks", sizeof(buf
));
472 blocksize
= 1024 * 1024;
473 strlcpy(buf
, "1MB-blocks", sizeof(buf
));
477 getbsize(&hlen
, &blocksize
);
478 snprintf(buf
, sizeof(buf
), "%ld-blocks", blocksize
);
482 if (sysctlbyname("vm.swap_info_array", NULL
, &bytes
, NULL
, 0) < 0)
483 err(1, "sysctlbyname()");
485 err(1, "sysctlbyname()");
487 xswbuf
= malloc(bytes
);
488 if (sysctlbyname("vm.swap_info_array", xswbuf
, &bytes
, NULL
, 0) < 0) {
490 err(1, "sysctlbyname()");
494 err(1, "sysctlbyname()");
498 * Calculate size of xsw entry returned by kernel (it can be larger
499 * than the one we have if there is a version mismatch).
501 ksize
= ((struct xswdev
*)xswbuf
)->xsw_size
;
502 n
= (int)(bytes
/ ksize
);
505 printf("%-13s %*s %*s\n",
511 total
= used
= tmp_total
= tmp_used
= 0;
512 for (i
= 0; i
< n
; ++i
) {
513 xsw
= (void *)((char *)xswbuf
+ i
* ksize
);
515 if (xsw
->xsw_nblks
== 0)
518 tmp_total
= (long long)xsw
->xsw_nblks
* pagesize
;
519 tmp_used
= (long long)xsw
->xsw_used
* pagesize
;
523 sizetobuf(buf
, sizeof(buf
), hflag
, tmp_total
, hlen
,
525 if (xsw
->xsw_dev
== NODEV
) {
526 printf("%-13s %s ", "[NFS swap]", buf
);
528 printf("/dev/%-8s %s ",
529 devname(xsw
->xsw_dev
, S_IFCHR
), buf
);
532 sizetobuf(buf
, sizeof(buf
), hflag
, tmp_used
, hlen
,
539 sizetobuf(buf
, sizeof(buf
), hflag
, total
, hlen
, blocksize
);
540 printf("Total: %s ", buf
);
541 sizetobuf(buf
, sizeof(buf
), hflag
, used
, hlen
, blocksize
);