From 41eba770616c36126cba3468a1781d212d3afb9d Mon Sep 17 00:00:00 2001 From: Jorgen Lundman Date: Fri, 16 Jul 2021 03:31:00 +0900 Subject: [PATCH] pass handle to do_unmount() The same change has already been done for domount(). On macOS platform we need to have access to zhp to handle devdisks and snapshots. Also, symmetry is pleasing. In addition, the code in zpool_disable_datasets which sorts the mountpoints did not sort the related handle, which meant that the mountpoint, and the handle that it is paired with, was lost. You'd get a random handle with the mountpoint. Reviewed-by: Brian Behlendorf Reviewed-by: John Kennedy Signed-off-by: Jorgen Lundman Closes #12296 --- lib/libzfs/libzfs_impl.h | 3 +- lib/libzfs/libzfs_mount.c | 73 +++++++++++++-------------- lib/libzfs/os/freebsd/libzfs_zmount.c | 2 +- lib/libzfs/os/linux/libzfs_mount_os.c | 2 +- 4 files changed, 39 insertions(+), 41 deletions(-) diff --git a/lib/libzfs/libzfs_impl.h b/lib/libzfs/libzfs_impl.h index ce7373582f0e..b1cf4f825f8a 100644 --- a/lib/libzfs/libzfs_impl.h +++ b/lib/libzfs/libzfs_impl.h @@ -243,7 +243,8 @@ extern proto_table_t proto_table[PROTO_END]; extern int do_mount(zfs_handle_t *zhp, const char *mntpt, char *opts, int flags); -extern int do_unmount(const char *mntpt, int flags); +extern int do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags); +extern int zfs_mount_delegation_check(void); extern int zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto); extern int zfs_unshare_proto(zfs_handle_t *, const char *, zfs_share_proto_t *); extern int unshare_one(libzfs_handle_t *hdl, const char *name, diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index b074a6e6f371..5729f120e9df 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -568,11 +568,11 @@ zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags, * Unmount a single filesystem. */ static int -unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags) +unmount_one(zfs_handle_t *zhp, const char *mountpoint, int flags) { int error; - error = do_unmount(mountpoint, flags); + error = do_unmount(zhp, mountpoint, flags); if (error != 0) { int libzfs_err; @@ -595,7 +595,7 @@ unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags) default: libzfs_err = EZFS_UMOUNTFAILED; } - return (zfs_error_fmt(hdl, libzfs_err, + return (zfs_error_fmt(zhp->zfs_hdl, libzfs_err, dgettext(TEXT_DOMAIN, "cannot unmount '%s'"), mountpoint)); } @@ -637,7 +637,7 @@ zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags) } zfs_commit_all_shares(); - if (unmount_one(hdl, mntpt, flags) != 0) { + if (unmount_one(zhp, mntpt, flags) != 0) { free(mntpt); (void) zfs_shareall(zhp); zfs_commit_all_shares(); @@ -1503,13 +1503,18 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags) return (ret); } +struct sets_s { + char *mountpoint; + zfs_handle_t *dataset; +}; + static int mountpoint_compare(const void *a, const void *b) { - const char *mounta = *((char **)a); - const char *mountb = *((char **)b); + const struct sets_s *mounta = (struct sets_s *)a; + const struct sets_s *mountb = (struct sets_s *)b; - return (strcmp(mountb, mounta)); + return (strcmp(mountb->mountpoint, mounta->mountpoint)); } /* @@ -1526,8 +1531,7 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) FILE *mnttab; struct mnttab entry; size_t namelen; - char **mountpoints = NULL; - zfs_handle_t **datasets = NULL; + struct sets_s *sets = NULL; libzfs_handle_t *hdl = zhp->zpool_hdl; int i; int ret = -1; @@ -1562,35 +1566,27 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) */ if (used == alloc) { if (alloc == 0) { - if ((mountpoints = zfs_alloc(hdl, - 8 * sizeof (void *))) == NULL) - goto out; - if ((datasets = zfs_alloc(hdl, - 8 * sizeof (void *))) == NULL) + if ((sets = zfs_alloc(hdl, + 8 * sizeof (struct sets_s))) == NULL) goto out; alloc = 8; } else { void *ptr; - if ((ptr = zfs_realloc(hdl, mountpoints, - alloc * sizeof (void *), - alloc * 2 * sizeof (void *))) == NULL) + if ((ptr = zfs_realloc(hdl, sets, + alloc * sizeof (struct sets_s), + alloc * 2 * sizeof (struct sets_s))) + == NULL) goto out; - mountpoints = ptr; - - if ((ptr = zfs_realloc(hdl, datasets, - alloc * sizeof (void *), - alloc * 2 * sizeof (void *))) == NULL) - goto out; - datasets = ptr; + sets = ptr; alloc *= 2; } } - if ((mountpoints[used] = zfs_strdup(hdl, + if ((sets[used].mountpoint = zfs_strdup(hdl, entry.mnt_mountp)) == NULL) goto out; @@ -1599,7 +1595,8 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) * is only used to determine if we need to remove the underlying * mountpoint, so failure is not fatal. */ - datasets[used] = make_dataset_handle(hdl, entry.mnt_special); + sets[used].dataset = make_dataset_handle(hdl, + entry.mnt_special); used++; } @@ -1608,7 +1605,7 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) * At this point, we have the entire list of filesystems, so sort it by * mountpoint. */ - qsort(mountpoints, used, sizeof (char *), mountpoint_compare); + qsort(sets, used, sizeof (struct sets_s), mountpoint_compare); /* * Walk through and first unshare everything. @@ -1617,9 +1614,9 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) zfs_share_proto_t *curr_proto; for (curr_proto = share_all_proto; *curr_proto != PROTO_END; curr_proto++) { - if (is_shared(mountpoints[i], *curr_proto) && - unshare_one(hdl, mountpoints[i], - mountpoints[i], *curr_proto) != 0) + if (is_shared(sets[i].mountpoint, *curr_proto) && + unshare_one(hdl, sets[i].mountpoint, + sets[i].mountpoint, *curr_proto) != 0) goto out; } } @@ -1630,25 +1627,25 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) * appropriate. */ for (i = 0; i < used; i++) { - if (unmount_one(hdl, mountpoints[i], flags) != 0) + if (unmount_one(sets[i].dataset, sets[i].mountpoint, + flags) != 0) goto out; } for (i = 0; i < used; i++) { - if (datasets[i]) - remove_mountpoint(datasets[i]); + if (sets[i].dataset) + remove_mountpoint(sets[i].dataset); } ret = 0; out: (void) fclose(mnttab); for (i = 0; i < used; i++) { - if (datasets[i]) - zfs_close(datasets[i]); - free(mountpoints[i]); + if (sets[i].dataset) + zfs_close(sets[i].dataset); + free(sets[i].mountpoint); } - free(datasets); - free(mountpoints); + free(sets); return (ret); } diff --git a/lib/libzfs/os/freebsd/libzfs_zmount.c b/lib/libzfs/os/freebsd/libzfs_zmount.c index e1febe6a2d91..6bc073cb03b9 100644 --- a/lib/libzfs/os/freebsd/libzfs_zmount.c +++ b/lib/libzfs/os/freebsd/libzfs_zmount.c @@ -121,7 +121,7 @@ do_mount(zfs_handle_t *zhp, const char *mntpt, char *opts, int flags) } int -do_unmount(const char *mntpt, int flags) +do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags) { if (unmount(mntpt, flags) < 0) return (errno); diff --git a/lib/libzfs/os/linux/libzfs_mount_os.c b/lib/libzfs/os/linux/libzfs_mount_os.c index 547895d7e370..42f300b36c91 100644 --- a/lib/libzfs/os/linux/libzfs_mount_os.c +++ b/lib/libzfs/os/linux/libzfs_mount_os.c @@ -374,7 +374,7 @@ do_mount(zfs_handle_t *zhp, const char *mntpt, char *opts, int flags) } int -do_unmount(const char *mntpt, int flags) +do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags) { if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) { int rv = umount2(mntpt, flags);