aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/mount_zfs/mount_zfs.c59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh42
2 files changed, 40 insertions, 61 deletions
diff --git a/cmd/mount_zfs/mount_zfs.c b/cmd/mount_zfs/mount_zfs.c
index 13935a9cc..0e7810703 100644
--- a/cmd/mount_zfs/mount_zfs.c
+++ b/cmd/mount_zfs/mount_zfs.c
@@ -43,53 +43,30 @@
libzfs_handle_t *g_zfs;
/*
- * Return the pool/dataset to mount given the name passed to mount. This
- * is expected to be of the form pool/dataset, however may also refer to
- * a block device if that device contains a valid zfs label.
+ * Opportunistically convert a target string into a pool name. If the
+ * string does not represent a block device with a valid zfs label
+ * then it is passed through without modification.
*/
static void
parse_dataset(const char *target, char **dataset)
{
- /*
- * We expect a pool/dataset to be provided, however if we're
- * given a device which is a member of a zpool we attempt to
- * extract the pool name stored in the label. Given the pool
- * name we can mount the root dataset.
- */
- int fd = open(target, O_RDONLY);
- if (fd >= 0) {
- nvlist_t *config = NULL;
- if (zpool_read_label(fd, &config, NULL) != 0)
- config = NULL;
- if (close(fd))
- perror("close");
-
- if (config) {
- char *name = NULL;
- if (!nvlist_lookup_string(config,
- ZPOOL_CONFIG_POOL_NAME, &name))
- (void) strlcpy(*dataset, name, PATH_MAX);
- nvlist_free(config);
- if (name)
- return;
- }
- }
+ /* Assume pool/dataset is more likely */
+ strlcpy(*dataset, target, PATH_MAX);
- /*
- * If a file or directory in your current working directory is
- * named 'dataset' then mount(8) will prepend your current working
- * directory to the dataset. There is no way to prevent this
- * behavior so we simply check for it and strip the prepended
- * patch when it is added.
- */
- char cwd[PATH_MAX];
- if (getcwd(cwd, PATH_MAX) != NULL) {
- int len = strlen(cwd);
- /* Do not add one when cwd already ends in a trailing '/' */
- if (strncmp(cwd, target, len) == 0)
- target += len + (cwd[len-1] != '/');
+ int fd = open(target, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ return;
+
+ nvlist_t *cfg = NULL;
+ if (zpool_read_label(fd, &cfg, NULL) == 0) {
+ char *nm = NULL;
+ if (!nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &nm))
+ strlcpy(*dataset, nm, PATH_MAX);
+ nvlist_free(cfg);
}
- strlcpy(*dataset, target, PATH_MAX);
+
+ if (close(fd))
+ perror("close");
}
/*
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh
index 9a62ffb02..810a69470 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh
@@ -25,15 +25,15 @@
verify_runnable "both"
set -A vdevs $(get_disklist_fullpath $TESTPOOL)
-vdev=${vdevs[0]}
-mntpoint=$TESTDIR/$TESTPOOL
-helper="mount.zfs -o zfsutil"
-fs=$TESTPOOL/$TESTFS
+typeset -r mntpoint=$(get_prop mountpoint $TESTPOOL)
+typeset -r helper="mount.zfs -o zfsutil"
+typeset -r fs=$TESTPOOL/$TESTFS
function cleanup
{
- log_must force_unmount $vdev
- [[ -d $mntpoint ]] && log_must rm -rf $mntpoint
+ cd $STF_SUITE
+ [[ -d $TESTDIR/$$ ]] && (rm -rf $TESTDIR/$$ || log_fail)
+ mounted && zfs $mountcmd $TESTPOOL
return 0
}
log_onexit cleanup
@@ -41,18 +41,21 @@ log_onexit cleanup
log_note "Verify zfs mount helper functions for both devices and pools"
# Ensure that the ZFS filesystem is unmounted
-force_unmount $fs
-log_must mkdir -p $mntpoint
+force_unmount $TESTPOOL
log_note "Verify '<dataset> <path>'"
log_must $helper $fs $mntpoint
log_must ismounted $fs
force_unmount $fs
-log_note "Verify '\$PWD/<pool> <path>' prefix workaround"
-log_must $helper $PWD/$fs $mntpoint
-log_must ismounted $fs
-force_unmount $fs
+log_note "Verify mount(8) does not canonicalize before calling helper"
+# Canonicalization is confused by files in PWD matching [device|mountpoint]
+mkdir -p $TESTDIR/$$/$TESTPOOL && cd $TESTDIR/$$ || log_fail
+# The env flag directs zfs to exec /bin/mount, which then calls helper
+log_must eval ZFS_MOUNT_HELPER=1 zfs $mountcmd -v $TESTPOOL
+# mount (2.35.2) still suffers from a cosmetic PWD prefix bug
+log_must mounted $TESTPOOL
+force_unmount $TESTPOOL
log_note "Verify '-f <dataset> <path>' fakemount"
log_must $helper -f $fs $mntpoint
@@ -63,14 +66,13 @@ log_must ${helper},ro -v $fs $mntpoint
log_must ismounted $fs
force_unmount $fs
-log_note "Verify '<device> <path>'"
-log_must $helper $vdev $mntpoint
-log_must ismounted $mntpoint
-log_must umount $TESTPOOL
-
log_note "Verify '-o abc -s <device> <path>' sloppy option"
-log_must ${helper},abc -s $vdev $mntpoint
-log_must ismounted $mntpoint
-log_must umount $TESTPOOL
+log_must ${helper},abc -s ${vdevs[0]} $mntpoint
+log_must mounted $mntpoint
+force_unmount $TESTPOOL
+
+log_note "Verify '<device> <path>'"
+log_must $helper ${vdevs[0]} $mntpoint
+log_must mounted $mntpoint
log_pass "zfs mount helper correctly handles both device and pool strings" \ No newline at end of file