Skip to content

Commit

Permalink
NEX-16219 pool import performance regression due to repeated libshare…
Browse files Browse the repository at this point in the history
… initialization

Reviewd by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
  • Loading branch information
joicemcintosh committed Mar 1, 2018
1 parent b844d82 commit 36ebdca
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 13 deletions.
2 changes: 1 addition & 1 deletion usr/src/cmd/zfs/zfs_main.c
Expand Up @@ -6634,7 +6634,7 @@ unshare_unmount(int op, int argc, char **argv)

/*
* Initilialize libshare SA_INIT_SHARE_API_SELECTIVE here
* to avoid unneccesary load/unload of the libshare plugins
* to avoid unneccesary load/unload of the libshare API
* per shared dataset downstream.
*/
if (op == OP_SHARE) {
Expand Down
16 changes: 15 additions & 1 deletion usr/src/lib/libshare/common/libshare.c
Expand Up @@ -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.
*/

Expand Down Expand Up @@ -1152,6 +1152,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
Expand Down
4 changes: 3 additions & 1 deletion usr/src/lib/libshare/common/libshare.h
Expand Up @@ -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.
*/

Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions usr/src/lib/libshare/common/mapfile-vers
Expand Up @@ -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.
#

#
Expand Down Expand Up @@ -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;
Expand Down
45 changes: 35 additions & 10 deletions usr/src/lib/libzfs/common/libzfs_mount.c
Expand Up @@ -575,6 +575,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 *);
Expand Down Expand Up @@ -617,6 +618,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,
Expand All @@ -640,10 +643,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;
Expand Down Expand Up @@ -802,11 +806,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.
Expand All @@ -816,8 +834,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"),
Expand Down Expand Up @@ -911,6 +928,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
Expand All @@ -920,13 +938,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"),
Expand Down Expand Up @@ -1678,7 +1703,7 @@ zpool_enable_datasets_ex(zpool_handle_t *zhp, const char *mntopts, int flags,

/*
* Initilialize libshare SA_INIT_SHARE_API_SELECTIVE here
* to avoid unneccesary load/unload of the libshare plugins
* to avoid unneccesary load/unload of the libshare API
* per shared dataset downstream.
*/
sharearg.zhandle_arr = cb.cb_handles;
Expand Down

0 comments on commit 36ebdca

Please sign in to comment.