902636
From bddf389330e11fb0ce17413c1bfa2264a281ded2 Mon Sep 17 00:00:00 2001
902636
From: Kevin Wolf <kwolf@redhat.com>
902636
Date: Mon, 30 Mar 2020 11:19:24 +0100
902636
Subject: [PATCH 4/4] mirror: Wait only for in-flight operations
902636
902636
RH-Author: Kevin Wolf <kwolf@redhat.com>
902636
Message-id: <20200330111924.22938-3-kwolf@redhat.com>
902636
Patchwork-id: 94463
902636
O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 2/2] mirror: Wait only for in-flight operations
902636
Bugzilla: 1794692
902636
RH-Acked-by: Maxim Levitsky <mlevitsk@redhat.com>
902636
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
902636
RH-Acked-by: Max Reitz <mreitz@redhat.com>
902636
902636
mirror_wait_for_free_in_flight_slot() just picks a random operation to
902636
wait for. However, a MirrorOp is already in s->ops_in_flight when
902636
mirror_co_read() waits for free slots, so if not enough slots are
902636
immediately available, an operation can end up waiting for itself, or
902636
two or more operations can wait for each other to complete, which
902636
results in a hang.
902636
902636
Fix this by adding a flag to MirrorOp that tells us if the request is
902636
already in flight (and therefore occupies slots that it will later
902636
free), and picking only such operations for waiting.
902636
902636
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1794692
902636
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
902636
Message-Id: <20200326153628.4869-3-kwolf@redhat.com>
902636
Reviewed-by: Eric Blake <eblake@redhat.com>
902636
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
902636
(cherry picked from commit ce8cabbd17cf738ddfc68384440c38e5dd2fdf97)
902636
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
902636
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
902636
---
902636
 block/mirror.c | 9 ++++++++-
902636
 1 file changed, 8 insertions(+), 1 deletion(-)
902636
902636
diff --git a/block/mirror.c b/block/mirror.c
902636
index 8959e42..5e5a521 100644
902636
--- a/block/mirror.c
902636
+++ b/block/mirror.c
902636
@@ -102,6 +102,7 @@ struct MirrorOp {
902636
 
902636
     bool is_pseudo_op;
902636
     bool is_active_write;
902636
+    bool is_in_flight;
902636
     CoQueue waiting_requests;
902636
     Coroutine *co;
902636
 
902636
@@ -293,7 +294,9 @@ mirror_wait_for_any_operation(MirrorBlockJob *s, bool active)
902636
          * caller of this function.  Since there is only one pseudo op
902636
          * at any given time, we will always find some real operation
902636
          * to wait on. */
902636
-        if (!op->is_pseudo_op && op->is_active_write == active) {
902636
+        if (!op->is_pseudo_op && op->is_in_flight &&
902636
+            op->is_active_write == active)
902636
+        {
902636
             qemu_co_queue_wait(&op->waiting_requests, NULL);
902636
             return;
902636
         }
902636
@@ -367,6 +370,7 @@ static void coroutine_fn mirror_co_read(void *opaque)
902636
     /* Copy the dirty cluster.  */
902636
     s->in_flight++;
902636
     s->bytes_in_flight += op->bytes;
902636
+    op->is_in_flight = true;
902636
     trace_mirror_one_iteration(s, op->offset, op->bytes);
902636
 
902636
     ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
902636
@@ -382,6 +386,7 @@ static void coroutine_fn mirror_co_zero(void *opaque)
902636
     op->s->in_flight++;
902636
     op->s->bytes_in_flight += op->bytes;
902636
     *op->bytes_handled = op->bytes;
902636
+    op->is_in_flight = true;
902636
 
902636
     ret = blk_co_pwrite_zeroes(op->s->target, op->offset, op->bytes,
902636
                                op->s->unmap ? BDRV_REQ_MAY_UNMAP : 0);
902636
@@ -396,6 +401,7 @@ static void coroutine_fn mirror_co_discard(void *opaque)
902636
     op->s->in_flight++;
902636
     op->s->bytes_in_flight += op->bytes;
902636
     *op->bytes_handled = op->bytes;
902636
+    op->is_in_flight = true;
902636
 
902636
     ret = blk_co_pdiscard(op->s->target, op->offset, op->bytes);
902636
     mirror_write_complete(op, ret);
902636
@@ -1306,6 +1312,7 @@ static MirrorOp *coroutine_fn active_write_prepare(MirrorBlockJob *s,
902636
         .offset             = offset,
902636
         .bytes              = bytes,
902636
         .is_active_write    = true,
902636
+        .is_in_flight       = true,
902636
     };
902636
     qemu_co_queue_init(&op->waiting_requests);
902636
     QTAILQ_INSERT_TAIL(&s->ops_in_flight, op, next);
902636
-- 
902636
1.8.3.1
902636