summaryrefslogtreecommitdiffstats
path: root/lib/libzfs/libzfs_mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libzfs/libzfs_mount.c')
-rw-r--r--lib/libzfs/libzfs_mount.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c
index 39ca2be05..7497a7223 100644
--- a/lib/libzfs/libzfs_mount.c
+++ b/lib/libzfs/libzfs_mount.c
@@ -668,6 +668,7 @@ zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags)
libzfs_handle_t *hdl = zhp->zfs_hdl;
struct mnttab entry;
char *mntpt = NULL;
+ boolean_t encroot, unmounted = B_FALSE;
/* check to see if we need to unmount the filesystem */
if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) &&
@@ -696,8 +697,33 @@ zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags)
(void) zfs_shareall(zhp);
return (-1);
}
+
libzfs_mnttab_remove(hdl, zhp->zfs_name);
free(mntpt);
+ unmounted = B_TRUE;
+ }
+
+ /*
+ * If the MS_CRYPT flag is provided we must ensure we attempt to
+ * unload the dataset's key regardless of whether we did any work
+ * to unmount it. We only do this for encryption roots.
+ */
+ if ((flags & MS_CRYPT) != 0 &&
+ zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) {
+ zfs_refresh_properties(zhp);
+
+ if (zfs_crypto_get_encryption_root(zhp, &encroot, NULL) != 0 &&
+ unmounted) {
+ (void) zfs_mount(zhp, NULL, 0);
+ return (-1);
+ }
+
+ if (encroot && zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) ==
+ ZFS_KEYSTATUS_AVAILABLE &&
+ zfs_crypto_unload_key(zhp) != 0) {
+ (void) zfs_mount(zhp, NULL, 0);
+ return (-1);
+ }
}
return (0);
@@ -715,7 +741,7 @@ zfs_unmountall(zfs_handle_t *zhp, int flags)
int ret;
clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
- CL_GATHER_ITER_MOUNTED, 0);
+ CL_GATHER_ITER_MOUNTED, flags);
if (clp == NULL)
return (-1);