|
|
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 |
|