Linux: Fix mount/unmount when dataset name has a space

The custom zpl_show_devname() helper should translate spaces in
to the octal escape sequence \040.  The getmntent(2) function
is aware of this convention and properly translates the escape
character back to a space when reading the fsname.

Without this change the `zfs mount` and `zfs unmount` commands
incorrectly detect when a dataset with a name containing spaces
is mounted.

Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #11182 
Closes #11187
This commit is contained in:
Brian Behlendorf 2020-11-11 17:14:24 -08:00 committed by GitHub
parent 18ca574f0a
commit c08d442e45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 4 deletions

View File

@ -185,13 +185,26 @@ zpl_remount_fs(struct super_block *sb, int *flags, char *data)
static int static int
__zpl_show_devname(struct seq_file *seq, zfsvfs_t *zfsvfs) __zpl_show_devname(struct seq_file *seq, zfsvfs_t *zfsvfs)
{ {
char *fsname;
ZFS_ENTER(zfsvfs); ZFS_ENTER(zfsvfs);
fsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
char *fsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
dmu_objset_name(zfsvfs->z_os, fsname); dmu_objset_name(zfsvfs->z_os, fsname);
seq_puts(seq, fsname);
for (int i = 0; fsname[i] != 0; i++) {
/*
* Spaces in the dataset name must be converted to their
* octal escape sequence for getmntent(3) to correctly
* parse then fsname portion of /proc/self/mounts.
*/
if (fsname[i] == ' ') {
seq_puts(seq, "\\040");
} else {
seq_putc(seq, fsname[i]);
}
}
kmem_free(fsname, ZFS_MAX_DATASET_NAME_LEN); kmem_free(fsname, ZFS_MAX_DATASET_NAME_LEN);
ZFS_EXIT(zfsvfs); ZFS_EXIT(zfsvfs);
return (0); return (0);

View File

@ -51,6 +51,8 @@ function cleanup
log_must zfs destroy -f ${datasets[$i]} log_must zfs destroy -f ${datasets[$i]}
((i = i + 1)) ((i = i + 1))
done done
zfs destroy -f "$TESTPOOL/with a space"
} }
log_onexit cleanup log_onexit cleanup
@ -68,4 +70,8 @@ while (( $i < ${#datasets[*]} )); do
((i = i + 1)) ((i = i + 1))
done done
log_must zfs create "$TESTPOOL/with a space"
log_must zfs unmount "$TESTPOOL/with a space"
log_must zfs mount "$TESTPOOL/with a space"
log_pass "'zfs create <filesystem>' works as expected." log_pass "'zfs create <filesystem>' works as expected."