From de0dd9a0e567c9977b913a59f30982ab997527bd Mon Sep 17 00:00:00 2001 From: Massimo Maggi Date: Fri, 18 Jan 2013 02:49:23 +0100 Subject: [PATCH] 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 (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. Author: Massimo Maggi --- module/zfs/zvol.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index d4d533f0231d..3b1e5348613b 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -921,23 +921,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); + 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); + goto out_mutex; } set_capacity(zv->zv_disk, volsize >> 9); @@ -952,6 +949,9 @@ zvol_first_open(zvol_state_t *zv) set_disk_ro(zv->zv_disk, 0); zv->zv_flags &= ~ZVOL_RDONLY; } +out_mutex: + if (locked) + mutex_exit(&spa_namespace_lock); return (-error); }