diff options
author | Massimo Maggi <[email protected]> | 2013-01-18 09:44:09 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2013-01-18 09:44:55 -0800 |
commit | babf3f9b6d9294b0a88457941d60af5d9d7b744d (patch) | |
tree | 54eb435cda3895eafa6bc3e04eff34718ddc923e /module | |
parent | 7973e464de4f93b6e669f7f04a316e013767224e (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')
-rw-r--r-- | module/zfs/zvol.c | 26 |
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); } |