summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2015-09-11 12:37:50 +0000
committeravg <avg@FreeBSD.org>2015-09-11 12:37:50 +0000
commitc26752881eb1f52599525dab13d8562da2ef8e5d (patch)
tree0d6e3c189ed9eba286090e457d6f595d8cbddaa0
parentfd504ef4095f1e46329b7aae92af510bd54d1d02 (diff)
downloadFreeBSD-src-c26752881eb1f52599525dab13d8562da2ef8e5d.zip
FreeBSD-src-c26752881eb1f52599525dab13d8562da2ef8e5d.tar.gz
MFC r286985: try to fix lor between z_teardown_lock and spa_namespace_lock
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
index 0ebc234..4d310d7 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -466,6 +466,19 @@ zfs_register_callbacks(vfs_t *vfsp)
}
/*
+ * We need to enter pool configuration here, so that we can use
+ * dsl_prop_get_int_ds() to handle the special nbmand property below.
+ * dsl_prop_get_integer() can not be used, because it has to acquire
+ * spa_namespace_lock and we can not do that because we already hold
+ * z_teardown_lock. The problem is that spa_config_sync() is called
+ * with spa_namespace_lock held and the function calls ZFS vnode
+ * operations to write the cache file and thus z_teardown_lock is
+ * acquired after spa_namespace_lock.
+ */
+ ds = dmu_objset_ds(os);
+ dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
+
+ /*
* nbmand is a special property. It can only be changed at
* mount time.
*
@@ -476,14 +489,9 @@ zfs_register_callbacks(vfs_t *vfsp)
nbmand = B_FALSE;
} else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) {
nbmand = B_TRUE;
- } else {
- char osname[MAXNAMELEN];
-
- dmu_objset_name(os, osname);
- if (error = dsl_prop_get_integer(osname, "nbmand", &nbmand,
- NULL)) {
- return (error);
- }
+ } else if (error = dsl_prop_get_int_ds(ds, "nbmand", &nbmand) != 0) {
+ dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
+ return (error);
}
/*
@@ -493,8 +501,6 @@ zfs_register_callbacks(vfs_t *vfsp)
* the first prop_register(), but I guess I like to go
* overboard...
*/
- ds = dmu_objset_ds(os);
- dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
error = dsl_prop_register(ds,
zfs_prop_to_name(ZFS_PROP_ATIME), atime_changed_cb, zfsvfs);
error = error ? error : dsl_prop_register(ds,
OpenPOWER on IntegriCloud