diff --git a/cmd/mount_zfs/mount_zfs.c b/cmd/mount_zfs/mount_zfs.c index 13935a9cc6..0e7810703e 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; - } - } - - /* - * 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] != '/'); - } + /* Assume pool/dataset is more likely */ strlcpy(*dataset, target, PATH_MAX); + + 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); + } + + 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 9a62ffb021..810a69470d 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 ' '" log_must $helper $fs $mntpoint log_must ismounted $fs force_unmount $fs -log_note "Verify '\$PWD/ ' 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 ' 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 ' '" -log_must $helper $vdev $mntpoint -log_must ismounted $mntpoint -log_must umount $TESTPOOL - log_note "Verify '-o abc -s ' 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 ' '" +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