diff --git a/usr.sbin/autofs/Makefile b/usr.sbin/autofs/Makefile --- a/usr.sbin/autofs/Makefile +++ b/usr.sbin/autofs/Makefile @@ -13,12 +13,18 @@ SRCS+= popen.c SRCS+= token.l +CFLAGS+=-DHAVE_ISSETUGID CFLAGS+=-I${.CURDIR} CFLAGS+=-I${SRCTOP}/sys/fs/autofs +CFLAGS+=-I${SRCTOP}/sys/contrib/openzfs/include/ +CFLAGS+=-I${SRCTOP}/sys/cddl/compat/opensolaris/ +CFLAGS+=-isystem ${SRCTOP}/sys/contrib/openzfs/lib/libspl/include/ +CFLAGS+=-isystem ${SRCTOP}/sys/contrib/openzfs/lib/libspl/include/os/freebsd/ +CFLAGS+=-isystem ${SRCTOP}/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys MAN= automount.8 automountd.8 autounmountd.8 auto_master.5 -LIBADD= util +LIBADD= util zfs # Needed for getmntopts.c MOUNT= ${SRCTOP}/sbin/mount diff --git a/usr.sbin/autofs/autounmountd.8 b/usr.sbin/autofs/autounmountd.8 --- a/usr.sbin/autofs/autounmountd.8 +++ b/usr.sbin/autofs/autounmountd.8 @@ -55,6 +55,8 @@ .Pp These options are available: .Bl -tag -width ".Fl v" +.It Fl c +Attempt to unload encryption keys whenever a ZFS mount is unmounted. .It Fl d Debug mode: increase verbosity and do not daemonize. .It Fl r diff --git a/usr.sbin/autofs/autounmountd.c b/usr.sbin/autofs/autounmountd.c --- a/usr.sbin/autofs/autounmountd.c +++ b/usr.sbin/autofs/autounmountd.c @@ -46,6 +46,8 @@ #include #include +#include + #include "common.h" #define AUTOUNMOUNTD_PIDFILE "/var/run/autounmountd.pid" @@ -55,6 +57,8 @@ time_t af_mount_time; bool af_mark; fsid_t af_fsid; + char af_fstype[MFSNAMELEN]; + char af_mountfrom[MNAMELEN]; char af_mountpoint[MNAMELEN]; }; @@ -74,7 +78,8 @@ } static struct automounted_fs * -automounted_add(fsid_t fsid, const char *mountpoint) +automounted_add(fsid_t fsid, const char *fstype, const char *mountpoint, + const char *mountfrom) { struct automounted_fs *af; @@ -83,7 +88,9 @@ log_err(1, "calloc"); af->af_mount_time = time(NULL); af->af_fsid = fsid; + strlcpy(af->af_fstype, fstype, sizeof(af->af_fstype)); strlcpy(af->af_mountpoint, mountpoint, sizeof(af->af_mountpoint)); + strlcpy(af->af_mountfrom, mountfrom, sizeof(af->af_mountfrom)); TAILQ_INSERT_TAIL(&automounted, af, af_next); @@ -133,7 +140,8 @@ "(FSID:%d:%d)", mntbuf[i].f_mntonname, mntbuf[i].f_fsid.val[0], mntbuf[i].f_fsid.val[1]); af = automounted_add(mntbuf[i].f_fsid, - mntbuf[i].f_mntonname); + mntbuf[i].f_fstypename, mntbuf[i].f_mntonname, + mntbuf[i].f_mntfromname); } else { log_debugx("already known automounted filesystem " "found on %s (FSID:%d:%d)", mntbuf[i].f_mntonname, @@ -152,16 +160,41 @@ } static int -unmount_by_fsid(const fsid_t fsid, const char *mountpoint) +unmount_by_fsid(const fsid_t fsid, const char *mountpoint, + const char *mountfrom, const char *fstype, libzfs_handle_t **libh, + bool unload_crypto_keys) { char *fsid_str; int error, ret; + zfs_handle_t *zfsh = NULL; ret = asprintf(&fsid_str, "FSID:%d:%d", fsid.val[0], fsid.val[1]); if (ret < 0) log_err(1, "asprintf"); - error = unmount(fsid_str, MNT_NONBUSY | MNT_BYFSID); + if (strcmp(fstype, "zfs") == 0) { + if (*libh == NULL && (*libh = libzfs_init()) == NULL) { + log_warn("cannot initialize ZFS (%s)", + strerror(errno)); + } else if ((zfsh = zfs_open(*libh, mountfrom, + ZFS_TYPE_FILESYSTEM)) == NULL) { + log_warn("cannot open ZFS dataset %s (%s)", + mountfrom, strerror(errno)); + } + } + + if (zfsh != NULL) { + int flags = 0; + + if (unload_crypto_keys) { + flags |= MS_CRYPT; + } + + error = zfs_unmount(zfsh, mountpoint, flags); + zfs_close(zfsh); + } else { + error = unmount(fsid_str, MNT_NONBUSY | MNT_BYFSID); + } if (error != 0) { if (errno == EBUSY) { log_debugx("cannot unmount %s (%s): %s", @@ -179,12 +212,13 @@ } static time_t -expire_automounted(time_t expiration_time) +expire_automounted(time_t expiration_time, bool unload_crypto_keys) { struct automounted_fs *af, *tmpaf; time_t now; time_t mounted_for, mounted_max = -1; int error; + libzfs_handle_t *libh = NULL; now = time(NULL); @@ -209,13 +243,18 @@ "was mounted for %ld seconds; unmounting", af->af_mountpoint, af->af_fsid.val[0], af->af_fsid.val[1], (long)mounted_for); - error = unmount_by_fsid(af->af_fsid, af->af_mountpoint); + error = unmount_by_fsid(af->af_fsid, af->af_mountpoint, + af->af_mountfrom, af->af_fstype, &libh, unload_crypto_keys); if (error != 0) { if (mounted_for > mounted_max) mounted_max = mounted_for; } } + if (libh != NULL) { + libzfs_fini(libh); + } + return (mounted_max); } @@ -270,9 +309,13 @@ int ch, debug = 0, error, kq; time_t expiration_time = 600, retry_time = 600, mounted_max, sleep_time; bool dont_daemonize = false; + bool unload_crypto_keys = false; - while ((ch = getopt(argc, argv, "dr:t:v")) != -1) { + while ((ch = getopt(argc, argv, "cdr:t:v")) != -1) { switch (ch) { + case 'c': + unload_crypto_keys = true; + break; case 'd': dont_daemonize = true; debug++; @@ -335,7 +378,8 @@ for (;;) { refresh_automounted(); - mounted_max = expire_automounted(expiration_time); + mounted_max = expire_automounted(expiration_time, + unload_crypto_keys); if (mounted_max == -1) { sleep_time = mounted_max; log_debugx("no filesystems to expire");