summaryrefslogtreecommitdiffstats
path: root/lib/libzfs
diff options
context:
space:
mode:
authorKyle Evans <[email protected]>2020-01-14 10:49:54 -0600
committerBrian Behlendorf <[email protected]>2020-01-14 08:49:54 -0800
commit68a192e4b7627f8f00d412ba68c291fcc90d3de9 (patch)
tree054fb7431ef982e15d01c53c9ab1a73afe54e590 /lib/libzfs
parente458fcca7516a0ceac7aaecc4aacfef1114eb216 (diff)
libzfs: add zfs_mount_at() function
zfs_mount_at() mounts a dataset at an arbitrary mountpoint rather than at the configured mountpoint. This may be used by consumers that wish to temporarily expose a dataset at another mountpoint without altering dataset/pool properties. This will be used by FreeBSD's libbe be_mount(), which mounts a boot environment at an arbitrary mountpoint. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Kyle Evans <[email protected]> Closes #9833
Diffstat (limited to 'lib/libzfs')
-rw-r--r--lib/libzfs/libzfs_mount.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c
index c2955ccfa..c3fe97d55 100644
--- a/lib/libzfs/libzfs_mount.c
+++ b/lib/libzfs/libzfs_mount.c
@@ -37,6 +37,7 @@
*
* zfs_is_mounted()
* zfs_mount()
+ * zfs_mount_at()
* zfs_unmount()
* zfs_unmountall()
*
@@ -240,6 +241,23 @@ zfs_is_mounted(zfs_handle_t *zhp, char **where)
}
/*
+ * Checks any higher order concerns about whether the given dataset is
+ * mountable, false otherwise. zfs_is_mountable_internal specifically assumes
+ * that the caller has verified the sanity of mounting the dataset at
+ * mountpoint to the extent the caller wants.
+ */
+static boolean_t
+zfs_is_mountable_internal(zfs_handle_t *zhp, const char *mountpoint)
+{
+
+ if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
+ getzoneid() == GLOBAL_ZONEID)
+ return (B_FALSE);
+
+ return (B_TRUE);
+}
+
+/*
* Returns true if the given dataset is mountable, false otherwise. Returns the
* mountpoint in 'buf'.
*/
@@ -264,8 +282,7 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
return (B_FALSE);
- if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
- getzoneid() == GLOBAL_ZONEID)
+ if (!zfs_is_mountable_internal(zhp, buf))
return (B_FALSE);
if (zfs_prop_get_int(zhp, ZFS_PROP_REDACTED) && !(flags & MS_FORCE))
@@ -346,14 +363,26 @@ zfs_add_options(zfs_handle_t *zhp, char *options, int len)
return (error);
}
+int
+zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
+{
+ char mountpoint[ZFS_MAXPROPLEN];
+
+ if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL,
+ flags))
+ return (0);
+
+ return (zfs_mount_at(zhp, options, flags, mountpoint));
+}
+
/*
* Mount the given filesystem.
*/
int
-zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
+zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags,
+ const char *mountpoint)
{
struct stat buf;
- char mountpoint[ZFS_MAXPROPLEN];
char mntopts[MNT_LINE_MAX];
char overlay[ZFS_MAXPROPLEN];
libzfs_handle_t *hdl = zhp->zfs_hdl;
@@ -369,16 +398,16 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
if (strstr(mntopts, MNTOPT_REMOUNT) != NULL)
remount = 1;
+ /* Potentially duplicates some checks if invoked by zfs_mount(). */
+ if (!zfs_is_mountable_internal(zhp, mountpoint))
+ return (0);
+
/*
* If the pool is imported read-only then all mounts must be read-only
*/
if (zpool_get_prop_int(zhp->zpool_hdl, ZPOOL_PROP_READONLY, NULL))
(void) strlcat(mntopts, "," MNTOPT_RO, sizeof (mntopts));
- if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL,
- flags))
- return (0);
-
/*
* Append default mount options which apply to the mount point.
* This is done because under Linux (unlike Solaris) multiple mount