Skip to content

Drop path prefix workaround #11295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 18 additions & 41 deletions cmd/mount_zfs/mount_zfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,37 @@
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

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
Expand All @@ -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"