try to fix lor between z_teardown_lock and spa_namespace_lock
The lock order reversal and a resulting deadlock were introduced in r285021 / D2865. The problem is that zfs_register_callbacks() calls dsl_prop_get_integer() that has to acquire spa_namespace_lock. At the same time, spa_config_sync() is called with spa_namespace_lock held and then it performs ZFS vnode operations that acquire z_teardown_lock in the reader mode. So, fix the problem by using dsl_prop_get_int_ds() instead of dsl_prop_get_integer(). The former does not need to look up the pool and the dataset by name. Reported by: many Reviewed by: delphij Tested by: delphij, Jens Schweikhardt <schweikh@schweikhardt.net> MFC after: 5 days X-MFC with: r285021
This commit is contained in:
parent
23d1046817
commit
243f5e3085
@ -471,6 +471,19 @@ zfs_register_callbacks(vfs_t *vfsp)
|
||||
do_atime = B_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -482,14 +495,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -499,8 +507,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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user