From: Brian Behlendorf Date: Wed, 12 Jul 2017 00:35:34 +0000 (-0400) Subject: Fix vdev_probe() call outside SCL_STATE_ALL lock X-Git-Tag: zfs-0.7.0-rc5~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc9c6bc;p=zfs 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 zinject -d -e io -T write -f 50 -L uber Reviewed-by: Olaf Faaland Signed-off-by: Brian Behlendorf Signed-off-by: Don Brady Closes #745 Closes #6279 --- 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);