aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/vdev_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/vdev_queue.c')
-rw-r--r--module/zfs/vdev_queue.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/module/zfs/vdev_queue.c b/module/zfs/vdev_queue.c
index f121eddc7..5d2c98013 100644
--- a/module/zfs/vdev_queue.c
+++ b/module/zfs/vdev_queue.c
@@ -517,6 +517,7 @@ static zio_t *
vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
{
zio_t *first, *last, *aio, *dio, *mandatory, *nio;
+ zio_link_t *zl = NULL;
uint64_t maxgap = 0;
uint64_t size;
uint64_t limit;
@@ -665,9 +666,18 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
zio_add_child(dio, aio);
vdev_queue_io_remove(vq, dio);
+ } while (dio != last);
+
+ /*
+ * We need to drop the vdev queue's lock to avoid a deadlock that we
+ * could encounter since this I/O will complete immediately.
+ */
+ mutex_exit(&vq->vq_lock);
+ while ((dio = zio_walk_parents(aio, &zl)) != NULL) {
zio_vdev_io_bypass(dio);
zio_execute(dio);
- } while (dio != last);
+ }
+ mutex_enter(&vq->vq_lock);
return (aio);
}