- Add vnode-backed swap space specification support. This is enabled when
device names "md" or "md[0-9]*" and a "file" option are specified in /etc/fstab like this: md none swap sw,file=/swap.bin 0 0 - Add GBDE/GELI encrypted swap space specification support, which rc.d/encswap supported. The /etc/fstab lines are like the following: /dev/ada1p1.bde none swap sw 0 0 /dev/ada1p2.eli none swap sw 0 0 .eli devices accepts aalgo, ealgo, keylen, and sectorsize as options. swapctl(8) can understand an encrypted device in the command line like this: # swapctl -a /dev/ada2p1.bde - "-L" flag is added to support "late" option to defer swapon until rc.d/mountlate runs. - rc.d script change: rc.d/encswap -> removed rc.d/addswap -> just display a warning message if $swapfile is defined rc.d/swap1 -> renamed to rc.d/swap rc.d/swaplate -> newly added to support "late" option These changes alleviate a race condition between device creation/removal and swapon/swapoff. MFC after: 1 week Reviewed by: wblock (manual page)
This commit is contained in:
parent
25fa33476b
commit
268a55bc98
@ -32,8 +32,6 @@ early_late_divider="FILESYSTEMS" # Script that separates early/late
|
||||
always_force_depends="NO" # Set to check that indicated dependencies are
|
||||
# running during boot (can increase boot time).
|
||||
|
||||
swapfile="NO" # Set to name of swapfile if aux swapfile desired.
|
||||
swapfile_mdunit="99" # Swapfile md(4) unit number created by mdconfig(8).
|
||||
apm_enable="NO" # Set to YES to enable APM BIOS functions (or NO).
|
||||
apmd_enable="NO" # Run apmd to handle APM event from userland.
|
||||
apmd_flags="" # Flags to apmd (if enabled).
|
||||
@ -85,9 +83,6 @@ geli_autodetach="YES" # Automatically detach on last close.
|
||||
#geli_da1_autodetach="NO"
|
||||
#geli_mirror_home_flags="-k /etc/geli/home.keys"
|
||||
|
||||
geli_swap_flags="-e aes -l 256 -s 4096 -d" # Options for GELI-encrypted
|
||||
# swap partitions.
|
||||
|
||||
root_rw_mount="YES" # Set to NO to inhibit remounting root read-write.
|
||||
fsck_y_enable="NO" # Set to YES to do fsck -y if the initial preen fails.
|
||||
fsck_y_flags="" # Additional flags for fsck -y
|
||||
|
@ -37,7 +37,6 @@ FILES= DAEMON \
|
||||
dhclient \
|
||||
dmesg \
|
||||
dumpon \
|
||||
encswap \
|
||||
faith \
|
||||
fsck \
|
||||
ftp-proxy \
|
||||
@ -139,7 +138,8 @@ FILES= DAEMON \
|
||||
static_arp \
|
||||
static_ndp \
|
||||
stf \
|
||||
swap1 \
|
||||
swap \
|
||||
swaplate \
|
||||
syscons \
|
||||
sysctl \
|
||||
syslogd \
|
||||
|
@ -13,57 +13,12 @@
|
||||
. /etc/rc.subr
|
||||
|
||||
name="addswap"
|
||||
start_cmd="addswap_start"
|
||||
stop_cmd="addswap_stop"
|
||||
start_cmd=":"
|
||||
stop_cmd=":"
|
||||
rcvar=
|
||||
|
||||
addswap_start()
|
||||
{
|
||||
case ${swapfile} in
|
||||
[Nn][Oo] | '')
|
||||
;;
|
||||
*)
|
||||
if [ -w "${swapfile}" ]; then
|
||||
check_startmsgs && echo "Adding ${swapfile} as additional swap"
|
||||
|
||||
if [ -n "${swapfile_mdunit}" ]; then
|
||||
mdev="/dev/md${swapfile_mdunit#md}"
|
||||
mdconfig -a -t vnode -f "${swapfile}" -u ${swapfile_mdunit}
|
||||
else
|
||||
mdev="/dev/`mdconfig -a -t vnode -f "${swapfile}"`"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
swapon ${mdev}
|
||||
else
|
||||
echo "error creating swapfile device"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
addswap_stop()
|
||||
{
|
||||
case ${swapfile} in
|
||||
[Nn][Oo] | '')
|
||||
;;
|
||||
*)
|
||||
if [ -n "${swapfile_mdunit}" ]; then
|
||||
mdev="/dev/md${swapfile_mdunit#md}"
|
||||
else
|
||||
mdev="/dev/`mdconfig -lv | grep "${swapfile}" | cut -f1`"
|
||||
swapfile_mdunit=${mdev#md}
|
||||
fi
|
||||
if [ -n "${swapfile_mdunit}" ]; then
|
||||
swapctl -l | grep -q ${mdev}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Dismounting swapfile ${swapfile}"
|
||||
swapoff ${mdev} && mdconfig -d -u ${swapfile_mdunit}
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
set_rcvar_obsolete swapfile
|
||||
set_rcvar_obsolete geli_swap_flags
|
||||
|
||||
load_rc_config $name
|
||||
run_rc_command "$1"
|
||||
|
@ -1,57 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
# PROVIDE: disks
|
||||
# REQUIRE: initrandom
|
||||
# KEYWORD: nojail
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="encswap"
|
||||
start_cmd="encswap_attach"
|
||||
stop_cmd="encswap_detach"
|
||||
|
||||
encswap_attach()
|
||||
{
|
||||
while read device mountpoint type options rest ; do
|
||||
case ":${device}:${type}:${options}" in
|
||||
:#*)
|
||||
continue
|
||||
;;
|
||||
*.bde:swap:sw)
|
||||
passphrase=`dd if=/dev/random count=1 2>/dev/null | md5 -q`
|
||||
device="${device%.bde}"
|
||||
gbde init "${device}" -P "${passphrase}" || return 1
|
||||
gbde attach "${device}" -p "${passphrase}" || return 1
|
||||
;;
|
||||
*.eli:swap:sw)
|
||||
device="${device%.eli}"
|
||||
geli onetime ${geli_swap_flags} "${device}" || return 1
|
||||
;;
|
||||
esac
|
||||
done < /etc/fstab
|
||||
}
|
||||
|
||||
encswap_detach()
|
||||
{
|
||||
while read device mountpoint type options rest ; do
|
||||
case ":${device}:${type}:${options}" in
|
||||
:#*)
|
||||
continue
|
||||
;;
|
||||
*.bde:swap:sw)
|
||||
device="${device%.bde}"
|
||||
gbde detach "${device}"
|
||||
;;
|
||||
*.eli:swap:sw)
|
||||
# Nothing here, because geli swap devices should be
|
||||
# created with the auto-detach-on-last-close option.
|
||||
;;
|
||||
esac
|
||||
done < /etc/fstab
|
||||
}
|
||||
|
||||
load_rc_config $name
|
||||
run_rc_command "$1"
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
|
||||
# PROVIDE: fsck
|
||||
# REQUIRE: localswap
|
||||
# REQUIRE: swap
|
||||
# KEYWORD: nojail
|
||||
|
||||
. /etc/rc.subr
|
||||
|
@ -28,7 +28,7 @@
|
||||
#
|
||||
|
||||
# PROVIDE: mdconfig
|
||||
# REQUIRE: localswap root
|
||||
# REQUIRE: swap root
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
|
@ -3,15 +3,15 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
# PROVIDE: localswap
|
||||
# PROVIDE: swap
|
||||
# REQUIRE: disks
|
||||
# KEYWORD: nojail shutdown
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="swap1"
|
||||
start_cmd='swapon -aq'
|
||||
name="swap"
|
||||
start_cmd='/sbin/swapon -aq'
|
||||
stop_cmd=':'
|
||||
|
||||
load_rc_config swap
|
||||
load_rc_config $name
|
||||
run_rc_command "$1"
|
17
etc/rc.d/swaplate
Executable file
17
etc/rc.d/swaplate
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
# PROVIDE: swaplate
|
||||
# REQUIRE: mountlate
|
||||
# KEYWORD: nojail shutdown
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="swaplate"
|
||||
start_cmd='/sbin/swapon -aLq'
|
||||
stop_cmd='/sbin/swapoff -aq'
|
||||
|
||||
load_rc_config swap
|
||||
run_rc_command "$1"
|
@ -57,6 +57,8 @@
|
||||
#define _PATH_ETC "/etc"
|
||||
#define _PATH_FTPUSERS "/etc/ftpusers"
|
||||
#define _PATH_FWMEM "/dev/fwmem"
|
||||
#define _PATH_GBDE "/sbin/gbde"
|
||||
#define _PATH_GELI "/sbin/geli"
|
||||
#define _PATH_HALT "/sbin/halt"
|
||||
#ifdef COMPAT_32BIT
|
||||
#define _PATH_I18NMODULE "/usr/lib32/i18n"
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" @(#)swapon.8 8.1 (Berkeley) 6/5/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 23, 2008
|
||||
.Dd June 21, 2013
|
||||
.Dt SWAPON 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -38,11 +38,11 @@
|
||||
.Nm swapon
|
||||
.Oo Fl F Ar fstab
|
||||
.Oc
|
||||
.Fl aq | Ar
|
||||
.Fl aLq | Ar
|
||||
.Nm swapoff
|
||||
.Oo Fl F Ar fstab
|
||||
.Oc
|
||||
.Fl aq | Ar
|
||||
.Fl aLq | Ar
|
||||
.Nm swapctl
|
||||
.Op Fl AghklmsU
|
||||
.Oo
|
||||
@ -74,10 +74,19 @@ option is used, all swap devices in
|
||||
.Pa /etc/fstab
|
||||
will be added, unless their
|
||||
.Dq noauto
|
||||
or
|
||||
.Dq late
|
||||
option is also set.
|
||||
If the
|
||||
.Fl L
|
||||
option is specified,
|
||||
swap devices with the
|
||||
.Dq late
|
||||
option will be added as well as ones with no option.
|
||||
If the
|
||||
.Fl q
|
||||
option is used informational messages will not be
|
||||
option is used,
|
||||
informational messages will not be
|
||||
written to standard output when a swap device is added.
|
||||
.Pp
|
||||
The
|
||||
@ -89,10 +98,19 @@ option is used, all swap devices in
|
||||
.Pa /etc/fstab
|
||||
will be removed, unless their
|
||||
.Dq noauto
|
||||
or
|
||||
.Dq late
|
||||
option is also set.
|
||||
If the
|
||||
.Fl L
|
||||
option is specified,
|
||||
swap devices with the
|
||||
.Dq late
|
||||
option will be removed as well as ones with no option.
|
||||
If the
|
||||
.Fl q
|
||||
option is used informational messages will not be
|
||||
option is used,
|
||||
informational messages will not be
|
||||
written to standard output when a swap device is removed.
|
||||
Note that
|
||||
.Nm swapoff
|
||||
|
@ -41,35 +41,51 @@ static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93";
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mdioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <fstab.h>
|
||||
#include <libgen.h>
|
||||
#include <libutil.h>
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <libutil.h>
|
||||
|
||||
static void usage(void);
|
||||
static int swap_on_off(char *name, int ignoreebusy);
|
||||
static const char *swap_on_off(char *, int, char *);
|
||||
static const char *swap_on_off_gbde(char *, int);
|
||||
static const char *swap_on_off_geli(char *, char *, int);
|
||||
static const char *swap_on_off_md(char *, char *, int);
|
||||
static const char *swap_on_off_sfile(char *, int);
|
||||
static void swaplist(int, int, int);
|
||||
static int run_cmd(int *, const char *, ...) __printflike(2, 3);
|
||||
|
||||
static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
|
||||
|
||||
static int qflag;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct fstab *fsp;
|
||||
const char *swfile;
|
||||
char *ptr;
|
||||
int ret;
|
||||
int ch, doall;
|
||||
int sflag = 0, lflag = 0, hflag = 0, qflag = 0;
|
||||
int sflag = 0, lflag = 0, late = 0, hflag = 0;
|
||||
const char *etc_fstab;
|
||||
|
||||
if ((ptr = strrchr(argv[0], '/')) == NULL)
|
||||
@ -82,7 +98,7 @@ main(int argc, char **argv)
|
||||
|
||||
doall = 0;
|
||||
etc_fstab = NULL;
|
||||
while ((ch = getopt(argc, argv, "AadghklmqsUF:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "AadghklLmqsUF:")) != -1) {
|
||||
switch(ch) {
|
||||
case 'A':
|
||||
if (which_prog == SWAPCTL) {
|
||||
@ -116,6 +132,9 @@ main(int argc, char **argv)
|
||||
case 'l':
|
||||
lflag = 1;
|
||||
break;
|
||||
case 'L':
|
||||
late = 1;
|
||||
break;
|
||||
case 'm':
|
||||
hflag = 'M';
|
||||
break;
|
||||
@ -145,6 +164,7 @@ main(int argc, char **argv)
|
||||
argv += optind;
|
||||
|
||||
ret = 0;
|
||||
swfile = NULL;
|
||||
if (etc_fstab != NULL)
|
||||
setfstab(etc_fstab);
|
||||
if (which_prog == SWAPON || which_prog == SWAPOFF) {
|
||||
@ -154,27 +174,37 @@ main(int argc, char **argv)
|
||||
continue;
|
||||
if (strstr(fsp->fs_mntops, "noauto"))
|
||||
continue;
|
||||
if (swap_on_off(fsp->fs_spec, 1)) {
|
||||
if (which_prog != SWAPOFF &&
|
||||
strstr(fsp->fs_mntops, "late") &&
|
||||
!late)
|
||||
continue;
|
||||
swfile = swap_on_off(fsp->fs_spec, 1,
|
||||
fsp->fs_mntops);
|
||||
if (swfile == NULL) {
|
||||
ret = 1;
|
||||
} else {
|
||||
if (!qflag) {
|
||||
printf("%s: %sing %s as swap device\n",
|
||||
getprogname(),
|
||||
which_prog == SWAPOFF ? "remov" : "add",
|
||||
fsp->fs_spec);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!qflag) {
|
||||
printf("%s: %sing %s as swap device\n",
|
||||
getprogname(),
|
||||
(which_prog == SWAPOFF) ?
|
||||
"remov" : "add", swfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!*argv)
|
||||
usage();
|
||||
for (; *argv; ++argv) {
|
||||
if (swap_on_off(*argv, 0)) {
|
||||
swfile = swap_on_off(*argv, 0, NULL);
|
||||
if (swfile == NULL) {
|
||||
ret = 1;
|
||||
} else if (orig_prog == SWAPCTL) {
|
||||
continue;
|
||||
}
|
||||
if (orig_prog == SWAPCTL) {
|
||||
printf("%s: %sing %s as swap device\n",
|
||||
getprogname(), which_prog == SWAPOFF ? "remov" : "add",
|
||||
*argv);
|
||||
getprogname(),
|
||||
(which_prog == SWAPOFF) ? "remov" : "add",
|
||||
swfile);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -186,14 +216,503 @@ main(int argc, char **argv)
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
swap_on_off(char *name, int doingall)
|
||||
static const char *
|
||||
swap_on_off(char *name, int doingall, char *mntops)
|
||||
{
|
||||
if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) {
|
||||
char base[PATH_MAX];
|
||||
|
||||
/* Swap on vnode-backed md(4) device. */
|
||||
if (mntops != NULL &&
|
||||
(fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) != FNM_NOMATCH ||
|
||||
fnmatch(MD_NAME "[0-9]*", name, 0) != FNM_NOMATCH ||
|
||||
strncmp(_PATH_DEV MD_NAME, name,
|
||||
sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 ||
|
||||
strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0))
|
||||
return (swap_on_off_md(name, mntops, doingall));
|
||||
|
||||
/* Swap on encrypted device by GEOM_BDE. */
|
||||
basename_r(name, base);
|
||||
if (fnmatch("*.bde", base, 0) != FNM_NOMATCH)
|
||||
return (swap_on_off_gbde(name, doingall));
|
||||
|
||||
/* Swap on encrypted device by GEOM_ELI. */
|
||||
if (fnmatch("*.eli", base, 0) != FNM_NOMATCH)
|
||||
return (swap_on_off_geli(name, mntops, doingall));
|
||||
|
||||
/* Swap on special file. */
|
||||
return (swap_on_off_sfile(name, doingall));
|
||||
}
|
||||
|
||||
static const char *
|
||||
swap_on_off_gbde(char *name, int doingall)
|
||||
{
|
||||
const char *ret;
|
||||
char pass[64 * 2 + 1], bpass[64];
|
||||
char *devname, *p;
|
||||
int i, fd, error;
|
||||
|
||||
devname = strdup(name);
|
||||
p = strrchr(devname, '.');
|
||||
if (p == NULL) {
|
||||
warnx("%s: Malformed device name", name);
|
||||
return (NULL);
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
fd = -1;
|
||||
switch (which_prog) {
|
||||
case SWAPON:
|
||||
arc4random_buf(bpass, sizeof(bpass));
|
||||
for (i = 0; i < (int)sizeof(bpass); i++)
|
||||
sprintf(&pass[2 * i], "%02x", bpass[i]);
|
||||
pass[sizeof(pass) - 1] = '\0';
|
||||
|
||||
error = run_cmd(&fd, "%s init %s -P %s", _PATH_GBDE,
|
||||
devname, pass);
|
||||
if (error) {
|
||||
/* bde device found. Ignore it. */
|
||||
close(fd);
|
||||
if (!qflag)
|
||||
warnx("%s: Device already in use", name);
|
||||
return (NULL);
|
||||
}
|
||||
close(fd);
|
||||
error = run_cmd(&fd, "%s attach %s -p %s", _PATH_GBDE,
|
||||
devname, pass);
|
||||
if (error) {
|
||||
close(fd);
|
||||
warnx("gbde (attach) error: %s", name);
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
case SWAPOFF:
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
break;
|
||||
}
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
ret = swap_on_off_sfile(name, doingall);
|
||||
|
||||
fd = -1;
|
||||
switch (which_prog) {
|
||||
case SWAPOFF:
|
||||
error = run_cmd(&fd, "%s detach %s", _PATH_GBDE, devname);
|
||||
if (error) {
|
||||
/* bde device not found. Ignore it. */
|
||||
if (!qflag)
|
||||
warnx("%s: Device not found", devname);
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static const char *
|
||||
swap_on_off_geli(char *name, char *mntops, int doingall)
|
||||
{
|
||||
const char *ops, *aalgo, *ealgo, *keylen_str, *sectorsize_str;
|
||||
char *devname, *p;
|
||||
char args[4096];
|
||||
struct stat sb;
|
||||
int fd, error, keylen, sectorsize;
|
||||
u_long ul;
|
||||
|
||||
devname = strdup(name);
|
||||
p = strrchr(devname, '.');
|
||||
if (p == NULL) {
|
||||
warnx("%s: Malformed device name", name);
|
||||
return (NULL);
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
ops = strdup(mntops);
|
||||
|
||||
/* Default parameters for geli(8). */
|
||||
aalgo = "hmac/sha256";
|
||||
ealgo = "aes";
|
||||
keylen = 256;
|
||||
sectorsize = 4096;
|
||||
|
||||
if ((p = strstr(ops, "aalgo=")) != NULL) {
|
||||
aalgo = p + sizeof("aalgo=") - 1;
|
||||
p = strchr(aalgo, ',');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
}
|
||||
if ((p = strstr(ops, "ealgo=")) != NULL) {
|
||||
ealgo = p + sizeof("ealgo=") - 1;
|
||||
p = strchr(ealgo, ',');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
}
|
||||
if ((p = strstr(ops, "keylen=")) != NULL) {
|
||||
keylen_str = p + sizeof("keylen=") - 1;
|
||||
p = strchr(keylen_str, ',');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
errno = 0;
|
||||
ul = strtoul(keylen_str, &p, 10);
|
||||
if (errno == 0) {
|
||||
if (*p != '\0' || ul > INT_MAX)
|
||||
errno = EINVAL;
|
||||
}
|
||||
if (errno) {
|
||||
warn("Invalid keylen: %s", keylen_str);
|
||||
return (NULL);
|
||||
}
|
||||
keylen = (int)ul;
|
||||
}
|
||||
if ((p = strstr(ops, "sectorsize=")) != NULL) {
|
||||
sectorsize_str = p + sizeof("sectorsize=") - 1;
|
||||
p = strchr(sectorsize_str, ',');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
errno = 0;
|
||||
ul = strtoul(sectorsize_str, &p, 10);
|
||||
if (errno == 0) {
|
||||
if (*p != '\0' || ul > INT_MAX)
|
||||
errno = EINVAL;
|
||||
}
|
||||
if (errno) {
|
||||
warn("Invalid sectorsize: %s", sectorsize_str);
|
||||
return (NULL);
|
||||
}
|
||||
sectorsize = (int)ul;
|
||||
}
|
||||
snprintf(args, sizeof(args), "-a %s -e %s -l %d -s %d -d",
|
||||
aalgo, ealgo, keylen, sectorsize);
|
||||
args[sizeof(args) - 1] = '\0';
|
||||
free((void *)ops);
|
||||
|
||||
fd = -1;
|
||||
switch (which_prog) {
|
||||
case SWAPON:
|
||||
error = run_cmd(&fd, "%s onetime %s %s", _PATH_GELI, args,
|
||||
devname);
|
||||
if (error) {
|
||||
/* eli device found. Ignore it. */
|
||||
close(fd);
|
||||
if (!qflag)
|
||||
warnx("%s: Device already in use "
|
||||
"or invalid parameters", name);
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
case SWAPOFF:
|
||||
if (stat(name, &sb) == -1 && errno == ENOENT) {
|
||||
if (!qflag)
|
||||
warnx("%s: Device not found", name);
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
break;
|
||||
}
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
|
||||
return (swap_on_off_sfile(name, doingall));
|
||||
}
|
||||
|
||||
static const char *
|
||||
swap_on_off_md(char *name, char *mntops, int doingall)
|
||||
{
|
||||
FILE *sfd;
|
||||
int fd, mdunit, error;
|
||||
const char *ret;
|
||||
char mdpath[PATH_MAX], linebuf[PATH_MAX];
|
||||
char *p, *vnodefile;
|
||||
size_t linelen;
|
||||
u_long ul;
|
||||
|
||||
fd = -1;
|
||||
sfd = NULL;
|
||||
if (strlen(name) == (sizeof(MD_NAME) - 1))
|
||||
mdunit = -1;
|
||||
else {
|
||||
errno = 0;
|
||||
ul = strtoul(name + 2, &p, 10);
|
||||
if (errno == 0) {
|
||||
if (*p != '\0' || ul > INT_MAX)
|
||||
errno = EINVAL;
|
||||
}
|
||||
if (errno) {
|
||||
warn("Bad device unit: %s", name);
|
||||
return (NULL);
|
||||
}
|
||||
mdunit = (int)ul;
|
||||
}
|
||||
|
||||
vnodefile = NULL;
|
||||
if ((p = strstr(mntops, "file=")) != NULL) {
|
||||
vnodefile = strdup(p + sizeof("file=") - 1);
|
||||
p = strchr(vnodefile, ',');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
}
|
||||
if (vnodefile == NULL) {
|
||||
warnx("file option not found for %s", name);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
switch (which_prog) {
|
||||
case SWAPON:
|
||||
if (mdunit == -1) {
|
||||
error = run_cmd(&fd, "%s -l -n -f %s",
|
||||
_PATH_MDCONFIG, vnodefile);
|
||||
if (error == 0) {
|
||||
/* md device found. Ignore it. */
|
||||
close(fd);
|
||||
if (!qflag)
|
||||
warnx("%s: Device already in use",
|
||||
vnodefile);
|
||||
return (NULL);
|
||||
}
|
||||
error = run_cmd(&fd, "%s -a -t vnode -n -f %s",
|
||||
_PATH_MDCONFIG, vnodefile);
|
||||
if (error) {
|
||||
warnx("mdconfig (attach) error: file=%s",
|
||||
vnodefile);
|
||||
return (NULL);
|
||||
}
|
||||
sfd = fdopen(fd, "r");
|
||||
if (sfd == NULL) {
|
||||
warn("mdconfig (attach) fdopen error");
|
||||
ret = NULL;
|
||||
goto err;
|
||||
}
|
||||
p = fgetln(sfd, &linelen);
|
||||
if (p == NULL &&
|
||||
(linelen < 2 || linelen > sizeof(linebuf))) {
|
||||
warn("mdconfig (attach) unexpected output");
|
||||
ret = NULL;
|
||||
goto err;
|
||||
}
|
||||
strncpy(linebuf, p, linelen);
|
||||
linebuf[linelen - 1] = '\0';
|
||||
errno = 0;
|
||||
ul = strtoul(linebuf, &p, 10);
|
||||
if (errno == 0) {
|
||||
if (*p != '\0' || ul > INT_MAX)
|
||||
errno = EINVAL;
|
||||
}
|
||||
if (errno) {
|
||||
warn("mdconfig (attach) unexpected output: %s",
|
||||
linebuf);
|
||||
ret = NULL;
|
||||
goto err;
|
||||
}
|
||||
mdunit = (int)ul;
|
||||
} else {
|
||||
error = run_cmd(&fd, "%s -l -n -f %s -u %d",
|
||||
_PATH_MDCONFIG, vnodefile, mdunit);
|
||||
if (error == 0) {
|
||||
/* md device found. Ignore it. */
|
||||
close(fd);
|
||||
if (!qflag)
|
||||
warnx("md%d on %s: Device already "
|
||||
"in use", mdunit, vnodefile);
|
||||
return (NULL);
|
||||
}
|
||||
error = run_cmd(NULL, "%s -a -t vnode -u %d -f %s",
|
||||
_PATH_MDCONFIG, mdunit, vnodefile);
|
||||
if (error) {
|
||||
warnx("mdconfig (attach) error: "
|
||||
"md%d on file=%s", mdunit, vnodefile);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SWAPOFF:
|
||||
if (mdunit == -1) {
|
||||
error = run_cmd(&fd, "%s -l -n -f %s",
|
||||
_PATH_MDCONFIG, vnodefile);
|
||||
if (error) {
|
||||
/* md device not found. Ignore it. */
|
||||
close(fd);
|
||||
if (!qflag)
|
||||
warnx("md on %s: Device not found",
|
||||
vnodefile);
|
||||
return (NULL);
|
||||
}
|
||||
sfd = fdopen(fd, "r");
|
||||
if (sfd == NULL) {
|
||||
warn("mdconfig (list) fdopen error");
|
||||
ret = NULL;
|
||||
goto err;
|
||||
}
|
||||
p = fgetln(sfd, &linelen);
|
||||
if (p == NULL &&
|
||||
(linelen < 2 || linelen > sizeof(linebuf) - 1)) {
|
||||
warn("mdconfig (list) unexpected output");
|
||||
ret = NULL;
|
||||
goto err;
|
||||
}
|
||||
strncpy(linebuf, p, linelen);
|
||||
linebuf[linelen - 1] = '\0';
|
||||
p = strchr(linebuf, ' ');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
errno = 0;
|
||||
ul = strtoul(linebuf, &p, 10);
|
||||
if (errno == 0) {
|
||||
if (*p != '\0' || ul > INT_MAX)
|
||||
errno = EINVAL;
|
||||
}
|
||||
if (errno) {
|
||||
warn("mdconfig (list) unexpected output: %s",
|
||||
linebuf);
|
||||
ret = NULL;
|
||||
goto err;
|
||||
}
|
||||
mdunit = (int)ul;
|
||||
} else {
|
||||
error = run_cmd(&fd, "%s -l -n -f %s -u %d",
|
||||
_PATH_MDCONFIG, vnodefile, mdunit);
|
||||
if (error) {
|
||||
/* md device not found. Ignore it. */
|
||||
close(fd);
|
||||
if (!qflag)
|
||||
warnx("md%d on %s: Device not found",
|
||||
mdunit, vnodefile);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV,
|
||||
MD_NAME, mdunit);
|
||||
mdpath[sizeof(mdpath) - 1] = '\0';
|
||||
ret = swap_on_off_sfile(mdpath, doingall);
|
||||
|
||||
switch (which_prog) {
|
||||
case SWAPOFF:
|
||||
if (ret != NULL) {
|
||||
error = run_cmd(NULL, "%s -d -u %d",
|
||||
_PATH_MDCONFIG, mdunit);
|
||||
if (error)
|
||||
warn("mdconfig (detach) detach failed: %s%s%d",
|
||||
_PATH_DEV, MD_NAME, mdunit);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
err:
|
||||
if (sfd != NULL)
|
||||
fclose(sfd);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
run_cmd(int *ofd, const char *cmdline, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char **argv, **argvp, *cmd, *p;
|
||||
int argc, pid, status, rv;
|
||||
int pfd[2], nfd, dup2dn;
|
||||
|
||||
va_start(ap, cmdline);
|
||||
rv = vasprintf(&cmd, cmdline, ap);
|
||||
if (rv == -1) {
|
||||
warn("%s", __func__);
|
||||
return (rv);
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
for (argc = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++)
|
||||
argc++;
|
||||
argv = (char **)malloc(sizeof(*argv) * (argc + 1));
|
||||
for (p = cmd, argvp = argv; (*argvp = strsep(&p, " ")) != NULL;)
|
||||
if (**argvp != '\0' && (++argvp > &argv[argc])) {
|
||||
*argvp = NULL;
|
||||
break;
|
||||
}
|
||||
/* The argv array ends up NULL-terminated here. */
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "DEBUG: running:");
|
||||
/* Should be equivalent to 'cmd' (before strsep, of course). */
|
||||
for (i = 0; argv[i] != NULL; i++)
|
||||
fprintf(stderr, " %s", argv[i]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
dup2dn = 1;
|
||||
if (ofd != NULL) {
|
||||
if (pipe(&pfd[0]) == -1) {
|
||||
warn("%s: pipe", __func__);
|
||||
return (-1);
|
||||
}
|
||||
*ofd = pfd[0];
|
||||
dup2dn = 0;
|
||||
}
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
case 0:
|
||||
/* Child process. */
|
||||
if (ofd != NULL)
|
||||
if (dup2(pfd[1], STDOUT_FILENO) < 0)
|
||||
err(1, "dup2 in %s", __func__);
|
||||
nfd = open(_PATH_DEVNULL, O_RDWR);
|
||||
if (nfd == -1)
|
||||
err(1, "%s: open %s", __func__, _PATH_DEVNULL);
|
||||
if (dup2(nfd, STDIN_FILENO) < 0)
|
||||
err(1, "%s: dup2", __func__);
|
||||
if (dup2dn && dup2(nfd, STDOUT_FILENO) < 0)
|
||||
err(1, "%s: dup2", __func__);
|
||||
if (dup2(nfd, STDERR_FILENO) < 0)
|
||||
err(1, "%s: dup2", __func__);
|
||||
execv(argv[0], argv);
|
||||
warn("exec: %s", argv[0]);
|
||||
_exit(-1);
|
||||
case -1:
|
||||
err(1, "%s: fork", __func__);
|
||||
}
|
||||
free(cmd);
|
||||
free(argv);
|
||||
while (waitpid(pid, &status, 0) != pid)
|
||||
;
|
||||
return (WEXITSTATUS(status));
|
||||
}
|
||||
|
||||
static const char *
|
||||
swap_on_off_sfile(char *name, int doingall)
|
||||
{
|
||||
int error;
|
||||
|
||||
switch (which_prog) {
|
||||
case SWAPON:
|
||||
error = swapon(name);
|
||||
break;
|
||||
case SWAPOFF:
|
||||
error = swapoff(name);
|
||||
break;
|
||||
default:
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
if (error == -1) {
|
||||
switch (errno) {
|
||||
case EBUSY:
|
||||
if (!doingall)
|
||||
warnx("%s: device already in use", name);
|
||||
warnx("%s: Device already in use", name);
|
||||
break;
|
||||
case EINVAL:
|
||||
if (which_prog == SWAPON)
|
||||
@ -205,9 +724,9 @@ swap_on_off(char *name, int doingall)
|
||||
warn("%s", name);
|
||||
break;
|
||||
}
|
||||
return(1);
|
||||
return (NULL);
|
||||
}
|
||||
return(0);
|
||||
return (name);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -217,7 +736,7 @@ usage(void)
|
||||
switch(orig_prog) {
|
||||
case SWAPON:
|
||||
case SWAPOFF:
|
||||
fprintf(stderr, "[-F fstab] -aq | file ...\n");
|
||||
fprintf(stderr, "[-F fstab] -aLq | file ...\n");
|
||||
break;
|
||||
case SWAPCTL:
|
||||
fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n");
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\" @(#)fstab.5 8.1 (Berkeley) 6/5/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 11, 2012
|
||||
.Dd June 21, 2013
|
||||
.Dt FSTAB 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -185,6 +185,15 @@ variable must be used to extend the
|
||||
.Xr rc 8
|
||||
startup script's list of network file system types.
|
||||
.Pp
|
||||
If the option
|
||||
.Dq late
|
||||
is specified, the file system will be automatically mounted
|
||||
at a stage of system startup after remote mount points are mounted.
|
||||
For more detail about this option,
|
||||
see the
|
||||
.Xr mount 8
|
||||
manual page.
|
||||
.Pp
|
||||
The type of the mount is extracted from the
|
||||
.Fa fs_mntops
|
||||
field and stored separately in the
|
||||
@ -202,6 +211,7 @@ then the file system whose name is given in the
|
||||
.Fa fs_file
|
||||
field is normally mounted read-write or read-only on the
|
||||
specified special file.
|
||||
.Pp
|
||||
If
|
||||
.Fa fs_type
|
||||
is
|
||||
@ -210,6 +220,25 @@ then the special file is made available as a piece of swap
|
||||
space by the
|
||||
.Xr swapon 8
|
||||
command at the end of the system reboot procedure.
|
||||
For vnode-backed swap spaces,
|
||||
.Dq file
|
||||
is supported in the
|
||||
.Fa fs_mntops
|
||||
field.
|
||||
When
|
||||
.Fa fs_spec
|
||||
is an
|
||||
.Xr md 4
|
||||
device file
|
||||
.Pq Do md Dc or Do md[0-9]* Dc
|
||||
and
|
||||
.Dq file
|
||||
is specified in
|
||||
.Fa fs_mntopts ,
|
||||
an
|
||||
.Xr md 4
|
||||
device is created with the specified file used as backing store,
|
||||
and then the new device is used as swap space.
|
||||
The fields other than
|
||||
.Fa fs_spec
|
||||
and
|
||||
|
Loading…
x
Reference in New Issue
Block a user