From 9f08b6e31f7ea0d174ba1d19a7f2d1cb48385b93 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Thu, 16 Feb 2023 17:10:52 -0500 Subject: [PATCH] Sync thread should avoid holding the spa config write lock when possible spa_sync() currently grabs the write lock due to an old hack that is documented by a comment: We need the write lock here because, for aux vdevs, calling vdev_config_dirty() modifies sav_config. This is ugly and will become unnecessary when we eliminate the aux vdev wart by integrating all vdevs into the root vdev tree. This has lead to deadlocks in rare edge cases from holding the write lock. We can reduce incidence of these deadlocks by not grabbing the write lock on pools without auxillary vdevs. Sponsored-By: Wasabi Technology, Inc. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14282 --- module/zfs/spa.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/module/zfs/spa.c b/module/zfs/spa.c index bbb83fc610..6be6fe1156 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -9281,7 +9281,13 @@ spa_sync(spa_t *spa, uint64_t txg) * into config changes that go out with this transaction group. */ spa_config_enter(spa, SCL_STATE, FTAG, RW_READER); - while (list_head(&spa->spa_state_dirty_list) != NULL) { + while ((vd = list_head(&spa->spa_state_dirty_list)) != NULL) { + /* Avoid holding the write lock unless actually necessary */ + if (vd->vdev_aux == NULL) { + vdev_state_clean(vd); + vdev_config_dirty(vd); + continue; + } /* * We need the write lock here because, for aux vdevs, * calling vdev_config_dirty() modifies sav_config.