diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/libshare/common/libshare.c | 15 | ||||
-rw-r--r-- | usr/src/lib/libshare/common/plugin.c | 35 |
2 files changed, 37 insertions, 13 deletions
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c index e5c5578c46..8fbf1e82ae 100644 --- a/usr/src/lib/libshare/common/libshare.c +++ b/usr/src/lib/libshare/common/libshare.c @@ -827,8 +827,14 @@ sa_init(int init_service) handle = calloc(sizeof (struct sa_handle_impl), 1); if (handle != NULL) { - /* get protocol specific structures */ - (void) proto_plugin_init(); + /* + * Get protocol specific structures, but only if this + * is the only handle. + */ + (void) mutex_lock(&sa_global_lock); + if (sa_global_handles == NULL) + (void) proto_plugin_init(); + (void) mutex_unlock(&sa_global_lock); if (init_service & SA_INIT_SHARE_API) { /* * initialize access into libzfs. We use this @@ -1030,10 +1036,13 @@ sa_fini(sa_handle_t handle) /* * If this was the last handle to release, unload the - * plugins that were loaded. + * plugins that were loaded. Use a mutex in case + * another thread is reinitializing. */ + (void) mutex_lock(&sa_global_lock); if (sa_global_handles == NULL) (void) proto_plugin_fini(); + (void) mutex_unlock(&sa_global_lock); } } diff --git a/usr/src/lib/libshare/common/plugin.c b/usr/src/lib/libshare/common/plugin.c index c2082b8a1a..2721715ef2 100644 --- a/usr/src/lib/libshare/common/plugin.c +++ b/usr/src/lib/libshare/common/plugin.c @@ -39,6 +39,8 @@ #include <dirent.h> #include <libintl.h> #include <sys/systeminfo.h> +#include <thread.h> +#include <synch.h> #define MAXISALEN 257 /* based on sysinfo(2) man page */ @@ -72,7 +74,6 @@ proto_plugin_init() { struct sa_proto_plugin *proto; int num_protos = 0; - int err; struct sa_plugin_ops *plugin_ops; void *dlhandle; DIR *dir; @@ -119,6 +120,9 @@ proto_plugin_init() sap_proto_list = proto; } else { ret = SA_NO_MEMORY; + /* Don't leak a dlhandle */ + (void) dlclose(dlhandle); + break; } } else { (void) fprintf(stderr, @@ -143,7 +147,8 @@ proto_plugin_init() for (i = 0, tmp = sap_proto_list; i < num_protos && tmp != NULL; tmp = tmp->plugin_next) { - err = 0; + int err; + err = SA_OK; if (tmp->plugin_ops->sa_init != NULL) err = tmp->plugin_ops->sa_init(); if (err == SA_OK) { @@ -159,13 +164,17 @@ proto_plugin_init() i++; } } + } else { + ret = SA_NO_MEMORY; } - } else { - /* - * There was an error, so cleanup prior to return of failure. - */ - proto_plugin_fini(); } + + /* + * There was an error, so cleanup prior to return of failure. + */ + if (ret != SA_OK) + proto_plugin_fini(); + return (ret); } @@ -214,14 +223,20 @@ static struct sa_plugin_ops * find_protocol(char *proto) { int i; + struct sa_plugin_ops *ops = NULL; + extern mutex_t sa_global_lock; + (void) mutex_lock(&sa_global_lock); if (proto != NULL) { for (i = 0; i < sa_proto_handle.sa_num_proto; i++) { - if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0) - return (sa_proto_handle.sa_ops[i]); + if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0) { + ops = sa_proto_handle.sa_ops[i]; + break; + } } } - return (NULL); + (void) mutex_unlock(&sa_global_lock); + return (ops); } /* |