yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

Blame SOURCES/kvm-mirror-Wait-only-for-in-flight-operations.patch

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