libzfs: add zfs_mount_at

This will be used in libbe in place of the internal zmount(); libbe only
wants to be able to mount a dataset at an arbitrary mountpoint without
altering dataset/pool properties. The natural way to do this in a portable
way is by creating a zfs_mount_at() interface that's effectively zfs_mount()
+ a mountpoint parameter. zfs_mount() is now a light wrapper around the new
method.

The interface and implementation have already been accepted into ZFS On
Linux, and the next commit to switch libbe() over to this new interface will
solve the last compatibility issue with ZoL.  The next sysutils/openzfs
rebase against ZoL should be able to build libbe/bectl with only minor
adjustments to build glue.

Reviewed by:	Ryan Moeller <ryan freqlabs com>
MFC after:	3 days
Differential Revision:	https://reviews.freebsd.org/D23132
This commit is contained in:
kevans 2020-01-19 02:45:02 +00:00
parent 9c51bb214a
commit a94ef72fbe
2 changed files with 27 additions and 5 deletions

View File

@ -769,6 +769,7 @@ extern ulong_t get_system_hostid(void);
extern boolean_t is_mounted(libzfs_handle_t *, const char *special, char **);
extern boolean_t zfs_is_mounted(zfs_handle_t *, char **);
extern int zfs_mount(zfs_handle_t *, const char *, int);
extern int zfs_mount_at(zfs_handle_t *, const char *, int, const char *);
extern int zfs_unmount(zfs_handle_t *, const char *, int);
extern int zfs_unmountall(zfs_handle_t *, int);

View File

@ -301,6 +301,17 @@ zfs_is_mounted(zfs_handle_t *zhp, char **where)
return (is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where));
}
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'.
@ -325,8 +336,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 (source)
@ -341,8 +351,19 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
int
zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
{
struct stat buf;
char mountpoint[ZFS_MAXPROPLEN];
if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
return (0);
return (zfs_mount_at(zhp, options, flags, mountpoint));
}
int
zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags,
const char *mountpoint)
{
struct stat buf;
char mntopts[MNT_LINE_MAX];
libzfs_handle_t *hdl = zhp->zfs_hdl;
@ -357,8 +378,8 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
if (zpool_get_prop_int(zhp->zpool_hdl, ZPOOL_PROP_READONLY, NULL))
flags |= MS_RDONLY;
if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
return (0);
if (!zfs_is_mountable_internal(zhp, mountpoint))
return (B_FALSE);
/* Create the directory if it doesn't already exist */
if (lstat(mountpoint, &buf) != 0) {