summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzfs/common/libzfs_mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libzfs/common/libzfs_mount.c')
-rw-r--r--usr/src/lib/libzfs/common/libzfs_mount.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_mount.c b/usr/src/lib/libzfs/common/libzfs_mount.c
index 44c0ec89e9..aea93fb91e 100644
--- a/usr/src/lib/libzfs/common/libzfs_mount.c
+++ b/usr/src/lib/libzfs/common/libzfs_mount.c
@@ -612,6 +612,7 @@ zfs_is_shared_smb(zfs_handle_t *zhp, char **where)
static sa_handle_t (*_sa_init)(int);
static sa_handle_t (*_sa_init_arg)(int, void *);
+static int (*_sa_service)(sa_handle_t);
static void (*_sa_fini)(sa_handle_t);
static sa_share_t (*_sa_find_share)(sa_handle_t, char *);
static int (*_sa_enable_share)(sa_share_t, char *);
@@ -654,6 +655,8 @@ _zfs_init_libshare(void)
_sa_init_arg = (sa_handle_t (*)(int, void *))dlsym(libshare,
"sa_init_arg");
_sa_fini = (void (*)(sa_handle_t))dlsym(libshare, "sa_fini");
+ _sa_service = (int (*)(sa_handle_t))dlsym(libshare,
+ "sa_service");
_sa_find_share = (sa_share_t (*)(sa_handle_t, char *))
dlsym(libshare, "sa_find_share");
_sa_enable_share = (int (*)(sa_share_t, char *))dlsym(libshare,
@@ -677,10 +680,11 @@ _zfs_init_libshare(void)
_sa_enable_share == NULL || _sa_disable_share == NULL ||
_sa_errorstr == NULL || _sa_parse_legacy_options == NULL ||
_sa_needs_refresh == NULL || _sa_get_zfs_handle == NULL ||
- _sa_zfs_process_share == NULL ||
+ _sa_zfs_process_share == NULL || _sa_service == NULL ||
_sa_update_sharetab_ts == NULL) {
_sa_init = NULL;
_sa_init_arg = NULL;
+ _sa_service = NULL;
_sa_fini = NULL;
_sa_disable_share = NULL;
_sa_enable_share = NULL;
@@ -839,11 +843,25 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
sa_share_t share;
zfs_share_proto_t *curr_proto;
zprop_source_t sourcetype;
+ int service = SA_INIT_ONE_SHARE_FROM_HANDLE;
int ret;
if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
return (0);
+ /*
+ * Function may be called in a loop from higher up stack, with libshare
+ * initialized for multiple shares (SA_INIT_SHARE_API_SELECTIVE).
+ * zfs_init_libshare_arg will refresh the handle's cache if necessary.
+ * In this case we do not want to switch to per share initialization.
+ * Specify SA_INIT_SHARE_API to do full refresh, if refresh required.
+ */
+ if ((hdl->libzfs_sharehdl != NULL) && (_sa_service != NULL) &&
+ (_sa_service(hdl->libzfs_sharehdl) ==
+ SA_INIT_SHARE_API_SELECTIVE)) {
+ service = SA_INIT_SHARE_API;
+ }
+
for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) {
/*
* Return success if there are no share options.
@@ -853,8 +871,7 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
ZFS_MAXPROPLEN, B_FALSE) != 0 ||
strcmp(shareopts, "off") == 0)
continue;
- ret = zfs_init_libshare_arg(hdl, SA_INIT_ONE_SHARE_FROM_HANDLE,
- zhp);
+ ret = zfs_init_libshare_arg(hdl, service, zhp);
if (ret != SA_OK) {
(void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
dgettext(TEXT_DOMAIN, "cannot share '%s': %s"),
@@ -948,6 +965,7 @@ unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
sa_share_t share;
int err;
char *mntpt;
+ int service = SA_INIT_ONE_SHARE_FROM_NAME;
/*
* Mountpoint could get trashed if libshare calls getmntany
@@ -957,13 +975,20 @@ unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
mntpt = zfs_strdup(hdl, mountpoint);
/*
- * make sure libshare initialized, initialize everything because we
- * don't know what other unsharing may happen later. Functions up the
- * stack are allowed to initialize instead a subset of shares at the
- * time the set is known.
+ * Function may be called in a loop from higher up stack, with libshare
+ * initialized for multiple shares (SA_INIT_SHARE_API_SELECTIVE).
+ * zfs_init_libshare_arg will refresh the handle's cache if necessary.
+ * In this case we do not want to switch to per share initialization.
+ * Specify SA_INIT_SHARE_API to do full refresh, if refresh required.
*/
- if ((err = zfs_init_libshare_arg(hdl, SA_INIT_ONE_SHARE_FROM_NAME,
- (void *)name)) != SA_OK) {
+ if ((hdl->libzfs_sharehdl != NULL) && (_sa_service != NULL) &&
+ (_sa_service(hdl->libzfs_sharehdl) ==
+ SA_INIT_SHARE_API_SELECTIVE)) {
+ service = SA_INIT_SHARE_API;
+ }
+
+ err = zfs_init_libshare_arg(hdl, service, (void *)name);
+ if (err != SA_OK) {
free(mntpt); /* don't need the copy anymore */
return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err,
dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
@@ -1532,9 +1557,9 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
ret = ms.ms_mntstatus;
/*
- * Share all filesystems that need to be shared. This needs to be
- * a separate pass because libshare is not mt-safe, and so we need
- * to share serially.
+ * Initialize libshare SA_INIT_SHARE_API_SELECTIVE here
+ * to avoid unnecessary load/unload of the libshare API
+ * per shared dataset downstream.
*/
sharearg.zhandle_arr = cb.cb_handles;
sharearg.zhandle_len = cb.cb_used;