From 748bf90148bbbaedd75fe1b2c47b3617710523bd Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Sat, 3 Jul 2021 00:16:36 +0300 Subject: [PATCH 1/3] block/mirror: fix active mirror dead-lock in mirror_wait_on_conflicts It's possible that requests start to wait each other in mirror_wait_on_conflicts(). To avoid it let's use same technique as in block/io.c in bdrv_wait_serialising_requests_locked() / bdrv_find_conflicting_request(): don't wait on intersecting request if it is already waiting for some other request. For details of the dead-lock look at testIntersectingActiveIO() test-case which we actually fixing now. Fixes: d06107ade0ce74dc39739bac80de84b51ec18546 Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20210702211636.228981-4-vsementsov@virtuozzo.com> Signed-off-by: Kevin Wolf Upstream-Status: Backport [d44dae1a7cf782ec9235746ebb0e6c1a20dd7288] Signed-off-by: Sakib Sajal --- block/mirror.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/block/mirror.c b/block/mirror.c index 8e1ad6ece..fab008568 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -106,6 +106,7 @@ struct MirrorOp { bool is_in_flight; CoQueue waiting_requests; Coroutine *co; + MirrorOp *waiting_for_op; QTAILQ_ENTRY(MirrorOp) next; }; @@ -158,7 +159,18 @@ static void coroutine_fn mirror_wait_on_conflicts(MirrorOp *self, if (ranges_overlap(self_start_chunk, self_nb_chunks, op_start_chunk, op_nb_chunks)) { + /* + * If the operation is already (indirectly) waiting for us, or + * will wait for us as soon as it wakes up, then just go on + * (instead of producing a deadlock in the former case). + */ + if (op->waiting_for_op) { + continue; + } + + self->waiting_for_op = op; qemu_co_queue_wait(&op->waiting_requests, NULL); + self->waiting_for_op = NULL; break; } } -- 2.33.0