diff options
author | Brian Behlendorf <[email protected]> | 2017-07-11 20:35:34 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-07-13 13:54:10 -0400 |
commit | cc9c6bcb7341cf37ccd4dfc939ec2abd4872e4bb (patch) | |
tree | a1021e5d429ef3f10a69cbcaa32502b1996547e4 /module | |
parent | 379ca9cf2beba802f096273e89e30914a2d6bafc (diff) |
Fix vdev_probe() call outside SCL_STATE_ALL lock
When an IO fails then zio_vdev_io_done() can call vdev_probe()
to determine the health of the vdev. This is safe as long as
the original zio was submitted with zio_wait() and holds the
SCL_STATE_ALL lock over the operation.
If zio_no_wait() was used then the done callback will submit
the probe IO outside the SCL_STATE_ALL lock and hit this
ASSERT in zio_create()
ASSERT(!vd || spa_config_held(spa, SCL_STATE_ALL, RW_READER));
Resolve the issue by only allowing vdev_probe() to be called
when there's a waiter indicating the caller is using zio_wait().
This assumes that caller is still holding SCL_STATE_ALL.
This issue isn't MMP specific but was surfaced when testing.
Without this patch it can be reproduced by running:
zpool set multihost on <pool>
zinject -d <vdev> -e io -T write -f 50 <pool> -L uber
Reviewed-by: Olaf Faaland <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Signed-off-by: Don Brady <[email protected]>
Closes #745
Closes #6279
Diffstat (limited to 'module')
-rw-r--r-- | module/zfs/zio.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c index acfc49eb5..fe47bb6b1 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -3325,7 +3325,7 @@ zio_vdev_io_done(zio_t *zio) ops->vdev_op_io_done(zio); - if (unexpected_error) + if (unexpected_error && zio->io_waiter != NULL) VERIFY(vdev_probe(vd, zio) == NULL); return (ZIO_PIPELINE_CONTINUE); |