changeset 14123:aba21162d62b

3944 libtopo zfs module will clobber libzfs handle when an instance of the module unloads Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com> Reviewed by: Boris Protopopov <boris.protopopov@nexenta.com> Reviewed by: Gary Mills <gary_mills@fastmail.fm> Reviewed by: Joshua M. Clulow <josh@sysmgr.org> Approved by: Dan McDonald <danmcd@nexenta.com>
author Alek Pinchuk <alek@nexenta.com>
date Mon, 05 Aug 2013 16:31:36 -0700
parents 1e57939bc87d
children 57414b906edf
files usr/src/lib/fm/topo/libtopo/common/zfs.c
diffstat 1 files changed, 22 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/fm/topo/libtopo/common/zfs.c	Wed Aug 07 12:16:22 2013 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/zfs.c	Mon Aug 05 16:31:36 2013 -0700
@@ -22,6 +22,7 @@
 
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <stdio.h>
@@ -41,6 +42,7 @@
 #include <topo_subr.h>
 #include <libzfs.h>
 #include <zfs.h>
+#include <pthread.h>
 
 static int zfs_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
     topo_instance_t, void *, void *);
@@ -59,7 +61,9 @@
 static const topo_modinfo_t zfs_info =
 	{ ZFS, FM_FMRI_SCHEME_ZFS, ZFS_VERSION, &zfs_ops };
 
-static libzfs_handle_t *g_zfs;
+static libzfs_handle_t *g_zfs = NULL;
+static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
+static int g_refcount = 0;
 
 int
 zfs_init(topo_mod_t *mod, topo_version_t version)
@@ -80,8 +84,18 @@
 		    "%s\n", topo_mod_errmsg(mod));
 		return (-1); /* mod errno already set */
 	}
-	if (!g_zfs)
-		g_zfs = libzfs_init();
+
+	(void) pthread_mutex_lock(&g_lock);
+	if (g_refcount == 0) {
+		if ((g_zfs = libzfs_init()) == NULL) {
+			(void) pthread_mutex_unlock(&g_lock);
+			topo_mod_dprintf(mod, "libzfs_init() failed");
+			topo_mod_unregister(mod);
+			return (topo_mod_seterrno(mod, EMOD_UNKNOWN));
+		}
+	}
+	g_refcount++;
+	(void) pthread_mutex_unlock(&g_lock);
 
 	return (0);
 }
@@ -89,10 +103,13 @@
 void
 zfs_fini(topo_mod_t *mod)
 {
-	if (g_zfs) {
+	(void) pthread_mutex_lock(&g_lock);
+	g_refcount--;
+	if (g_refcount == 0) {
 		libzfs_fini(g_zfs);
 		g_zfs = NULL;
 	}
+	(void) pthread_mutex_unlock(&g_lock);
 	topo_mod_unregister(mod);
 }
 
@@ -155,7 +172,7 @@
 	cb.cb_guid = pool_guid;
 	cb.cb_pool = NULL;
 
-	if (g_zfs != NULL && zpool_iter(g_zfs, find_pool, &cb) == 1) {
+	if (zpool_iter(g_zfs, find_pool, &cb) == 1) {
 		name = zpool_get_name(cb.cb_pool);
 	} else {
 		(void) snprintf(guidbuf, sizeof (guidbuf), "%llx", pool_guid);