diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/zfs/zfs_main.c | 24 | ||||
-rw-r--r-- | usr/src/lib/libshare/common/libshare.c | 16 | ||||
-rw-r--r-- | usr/src/lib/libshare/common/libshare.h | 4 | ||||
-rw-r--r-- | usr/src/lib/libshare/common/mapfile-vers | 2 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_mount.c | 49 |
5 files changed, 81 insertions, 14 deletions
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c index cfed8bc4f8..bd2f7f4cfe 100644 --- a/usr/src/cmd/zfs/zfs_main.c +++ b/usr/src/cmd/zfs/zfs_main.c @@ -6849,6 +6849,30 @@ unshare_unmount(int op, int argc, char **argv) } /* + * Initialize libshare SA_INIT_SHARE_API_SELECTIVE here + * to avoid unnecessary load/unload of the libshare API + * per shared dataset downstream. + */ + if (op == OP_SHARE) { + get_all_cb_t dslist = { 0 }; + get_all_datasets(&dslist, B_FALSE); + + if (dslist.cb_used != 0) { + sa_init_selective_arg_t sharearg; + sharearg.zhandle_arr = dslist.cb_handles; + sharearg.zhandle_len = dslist.cb_used; + if ((ret = zfs_init_libshare_arg(g_zfs, + SA_INIT_SHARE_API_SELECTIVE, &sharearg)) != + SA_OK) { + (void) fprintf(stderr, gettext( + "Could not initialize libshare, " + "%d"), ret); + return (1); + } + } + } + + /* * Walk the AVL tree in reverse, unmounting each filesystem and * removing it from the AVL tree in the process. */ diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c index 5a58e0268e..a507e8a1a5 100644 --- a/usr/src/lib/libshare/common/libshare.c +++ b/usr/src/lib/libshare/common/libshare.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. */ @@ -1153,6 +1153,20 @@ sa_fini(sa_handle_t handle) } /* + * sa_service(sa_handle_t handle) + * + * Returns the service for which the handle is currently initialized. + */ +int +sa_service(sa_handle_t handle) +{ + if (handle == NULL) + return (0); + + return (((sa_handle_impl_t)handle)->sa_service); +} + +/* * sa_get_protocols(char **protocol) * Get array of protocols that are supported * Returns pointer to an allocated and NULL terminated diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h index 7ad9fefdcd..042a6f8cee 100644 --- a/usr/src/lib/libshare/common/libshare.h +++ b/usr/src/lib/libshare/common/libshare.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. */ @@ -171,6 +171,8 @@ typedef struct sa_init_selective_arg sa_init_selective_arg_t; extern sa_handle_t sa_init(int); extern sa_handle_t sa_init_arg(int, void *); extern void sa_fini(sa_handle_t); +extern int sa_service(sa_handle_t); + extern int sa_update_config(sa_handle_t); extern boolean_t sa_needs_refresh(sa_handle_t); extern char *sa_errorstr(int); diff --git a/usr/src/lib/libshare/common/mapfile-vers b/usr/src/lib/libshare/common/mapfile-vers index de74d62038..c661589eda 100644 --- a/usr/src/lib/libshare/common/mapfile-vers +++ b/usr/src/lib/libshare/common/mapfile-vers @@ -21,6 +21,7 @@ # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2016 by Delphix. All rights reserved. +# Copyright 2018 Nexenta Systems, Inc. All rights reserved. # # @@ -114,6 +115,7 @@ SYMBOL_VERSION SUNWprivate { sa_get_protocol_status; sa_init; sa_init_arg; + sa_service; sa_find_share; sa_set_protocol_property; sa_fini; 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; |