summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorMassimo Maggi <[email protected]>2013-01-18 09:44:09 -0800
committerBrian Behlendorf <[email protected]>2013-01-18 09:44:55 -0800
commitbabf3f9b6d9294b0a88457941d60af5d9d7b744d (patch)
tree54eb435cda3895eafa6bc3e04eff34718ddc923e /module/zfs
parent7973e464de4f93b6e669f7f04a316e013767224e (diff)
Fix zpool on zvol deadlock
Commit 65d56083b4617a4cade0cff68cbbaf68114169d6 fixes the lock inversion between spa_namespace_lock and bdev->bd_mutex but only for the first user of spa_namespace_lock: dmu_objset_own(). Later spa_namespace_lock gets acquired by dsl_prop_get_integer() though dsl_prop_get()->dsl_dataset_hold()->dsl_dir_open_spa()-> spa_open()->spa_open_common() without this "protection". By moving the mutex release after this second use, even this acquisition of the lock is "protected" by the ERESTARTSYS trick. Signed-off-by: Massimo Maggi <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #1220
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/zvol.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index d4d533f02..c6cfac26d 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -920,24 +920,20 @@ zvol_first_open(zvol_state_t *zv)
/* lie and say we're read-only */
error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, 1, zvol_tag, &os);
-
- if (locked)
- mutex_exit(&spa_namespace_lock);
-
if (error)
- return (-error);
+ goto out_mutex;
error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
if (error) {
- dmu_objset_disown(os, zvol_tag);
- return (-error);
+ dmu_objset_disown(os, zvol_tag);
+ goto out_mutex;
}
zv->zv_objset = os;
error = dmu_bonus_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dbuf);
if (error) {
- dmu_objset_disown(os, zvol_tag);
- return (-error);
+ dmu_objset_disown(os, zvol_tag);
+ goto out_mutex;
}
set_capacity(zv->zv_disk, volsize >> 9);
@@ -946,13 +942,17 @@ zvol_first_open(zvol_state_t *zv)
VERIFY(dsl_prop_get_integer(zv->zv_name, "readonly", &ro, NULL) == 0);
if (ro || dmu_objset_is_snapshot(os)) {
- set_disk_ro(zv->zv_disk, 1);
- zv->zv_flags |= ZVOL_RDONLY;
+ set_disk_ro(zv->zv_disk, 1);
+ zv->zv_flags |= ZVOL_RDONLY;
} else {
- set_disk_ro(zv->zv_disk, 0);
- zv->zv_flags &= ~ZVOL_RDONLY;
+ set_disk_ro(zv->zv_disk, 0);
+ zv->zv_flags &= ~ZVOL_RDONLY;
}
+out_mutex:
+ if (locked)
+ mutex_exit(&spa_namespace_lock);
+
return (-error);
}