diff options
author | Olaf Faaland <[email protected]> | 2017-07-24 08:48:28 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-07-25 12:25:05 -0400 |
commit | ffb195c256f8a74a87c3834258ec90c513d66adb (patch) | |
tree | 07c0c43142ed997d8d5105ca05c802a859b8cd77 /module | |
parent | f43615d0cc22d7db496c1291c84e64e269ca51d9 (diff) |
Release SCL_STATE in map_write_done()
The config lock must be held for the duration of the MMP write.
Since the I/Os are executed via map_nowait(), the done function
is the only place where we know the write has completed.
Since SCL_STATE is taken as reader, overlapping I/Os do not
create a deadlock. The refcount is simply increased when new
I/Os are queued and decreased when I/Os complete.
Test case added which exercises the probe IO call path to
verify the fix and prevent a regression.
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Olaf Faaland <[email protected]>
Closes #6394
Diffstat (limited to 'module')
-rw-r--r-- | module/zfs/mmp.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/module/zfs/mmp.c b/module/zfs/mmp.c index ae5478a33..539b76826 100644 --- a/module/zfs/mmp.c +++ b/module/zfs/mmp.c @@ -287,6 +287,7 @@ mmp_write_done(zio_t *zio) unlock: mutex_exit(&mts->mmp_io_lock); + spa_config_exit(spa, SCL_STATE, FTAG); abd_free(zio->io_abd); } @@ -322,9 +323,12 @@ mmp_write_uberblock(spa_t *spa) int label; uint64_t offset; + spa_config_enter(spa, SCL_STATE, FTAG, RW_READER); vd = vdev_random_leaf(spa); - if (vd == NULL || !vdev_writeable(vd)) + if (vd == NULL || !vdev_writeable(vd)) { + spa_config_exit(spa, SCL_STATE, FTAG); return; + } mutex_enter(&mmp->mmp_io_lock); @@ -437,11 +441,8 @@ mmp_thread(spa_t *spa) zio_suspend(spa, NULL); } - if (multihost) { - spa_config_enter(spa, SCL_STATE, FTAG, RW_READER); + if (multihost) mmp_write_uberblock(spa); - spa_config_exit(spa, SCL_STATE, FTAG); - } CALLB_CPR_SAFE_BEGIN(&cpr); (void) cv_timedwait_sig(&mmp->mmp_thread_cv, |