From: @kuhnchen18 Reviewed-by: @imxcc Signed-off-by: @imxcc
This commit is contained in:
commit
f814f65ab1
83
mirror-Wait-only-for-in-flight-operations.patch
Normal file
83
mirror-Wait-only-for-in-flight-operations.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
From b4e1ea1c59e4dd8cc95b97ccc4eb1d3957fe5489 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Date: Thu, 26 Mar 2020 16:36:28 +0100
|
||||||
|
Subject: [PATCH] mirror: Wait only for in-flight operations
|
||||||
|
|
||||||
|
mirror_wait_for_free_in_flight_slot() just picks a random operation to
|
||||||
|
wait for. However, a MirrorOp is already in s->ops_in_flight when
|
||||||
|
mirror_co_read() waits for free slots, so if not enough slots are
|
||||||
|
immediately available, an operation can end up waiting for itself, or
|
||||||
|
two or more operations can wait for each other to complete, which
|
||||||
|
results in a hang.
|
||||||
|
|
||||||
|
Fix this by adding a flag to MirrorOp that tells us if the request is
|
||||||
|
already in flight (and therefore occupies slots that it will later
|
||||||
|
free), and picking only such operations for waiting.
|
||||||
|
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1794692
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Message-Id: <20200326153628.4869-3-kwolf@redhat.com>
|
||||||
|
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
---
|
||||||
|
block/mirror.c | 9 ++++++++-
|
||||||
|
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/block/mirror.c b/block/mirror.c
|
||||||
|
index 8f0d4544d8..abcf60a961 100644
|
||||||
|
--- a/block/mirror.c
|
||||||
|
+++ b/block/mirror.c
|
||||||
|
@@ -100,6 +100,7 @@ struct MirrorOp {
|
||||||
|
|
||||||
|
bool is_pseudo_op;
|
||||||
|
bool is_active_write;
|
||||||
|
+ bool is_in_flight;
|
||||||
|
CoQueue waiting_requests;
|
||||||
|
|
||||||
|
QTAILQ_ENTRY(MirrorOp) next;
|
||||||
|
@@ -290,7 +291,9 @@ mirror_wait_for_any_operation(MirrorBlockJob *s, bool active)
|
||||||
|
* caller of this function. Since there is only one pseudo op
|
||||||
|
* at any given time, we will always find some real operation
|
||||||
|
* to wait on. */
|
||||||
|
- if (!op->is_pseudo_op && op->is_active_write == active) {
|
||||||
|
+ if (!op->is_pseudo_op && op->is_in_flight &&
|
||||||
|
+ op->is_active_write == active)
|
||||||
|
+ {
|
||||||
|
qemu_co_queue_wait(&op->waiting_requests, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@@ -364,6 +367,7 @@ static void coroutine_fn mirror_co_read(void *opaque)
|
||||||
|
/* Copy the dirty cluster. */
|
||||||
|
s->in_flight++;
|
||||||
|
s->bytes_in_flight += op->bytes;
|
||||||
|
+ op->is_in_flight = true;
|
||||||
|
trace_mirror_one_iteration(s, op->offset, op->bytes);
|
||||||
|
|
||||||
|
ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
|
||||||
|
@@ -379,6 +383,7 @@ static void coroutine_fn mirror_co_zero(void *opaque)
|
||||||
|
op->s->in_flight++;
|
||||||
|
op->s->bytes_in_flight += op->bytes;
|
||||||
|
*op->bytes_handled = op->bytes;
|
||||||
|
+ op->is_in_flight = true;
|
||||||
|
|
||||||
|
ret = blk_co_pwrite_zeroes(op->s->target, op->offset, op->bytes,
|
||||||
|
op->s->unmap ? BDRV_REQ_MAY_UNMAP : 0);
|
||||||
|
@@ -393,6 +398,7 @@ static void coroutine_fn mirror_co_discard(void *opaque)
|
||||||
|
op->s->in_flight++;
|
||||||
|
op->s->bytes_in_flight += op->bytes;
|
||||||
|
*op->bytes_handled = op->bytes;
|
||||||
|
+ op->is_in_flight = true;
|
||||||
|
|
||||||
|
ret = blk_co_pdiscard(op->s->target, op->offset, op->bytes);
|
||||||
|
mirror_write_complete(op, ret);
|
||||||
|
@@ -1305,6 +1311,7 @@ static MirrorOp *coroutine_fn active_write_prepare(MirrorBlockJob *s,
|
||||||
|
.offset = offset,
|
||||||
|
.bytes = bytes,
|
||||||
|
.is_active_write = true,
|
||||||
|
+ .is_in_flight = true,
|
||||||
|
};
|
||||||
|
qemu_co_queue_init(&op->waiting_requests);
|
||||||
|
QTAILQ_INSERT_TAIL(&s->ops_in_flight, op, next);
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
39
qcow2-Fix-qcow2_alloc_cluster_abort-for-external-dat.patch
Normal file
39
qcow2-Fix-qcow2_alloc_cluster_abort-for-external-dat.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
From fad649b88c93d0567be4e426f23063b439037095 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Date: Tue, 11 Feb 2020 10:48:59 +0100
|
||||||
|
Subject: [PATCH] qcow2: Fix qcow2_alloc_cluster_abort() for external data file
|
||||||
|
|
||||||
|
For external data file, cluster allocations return an offset in the data
|
||||||
|
file and are not refcounted. In this case, there is nothing to do for
|
||||||
|
qcow2_alloc_cluster_abort(). Freeing the same offset in the qcow2 file
|
||||||
|
is wrong and causes crashes in the better case or image corruption in
|
||||||
|
the worse case.
|
||||||
|
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Message-Id: <20200211094900.17315-3-kwolf@redhat.com>
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
---
|
||||||
|
block/qcow2-cluster.c | 7 +++++--
|
||||||
|
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
|
||||||
|
index f8576031b6..7e7e051437 100644
|
||||||
|
--- a/block/qcow2-cluster.c
|
||||||
|
+++ b/block/qcow2-cluster.c
|
||||||
|
@@ -1026,8 +1026,11 @@ err:
|
||||||
|
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
|
||||||
|
{
|
||||||
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
- qcow2_free_clusters(bs, m->alloc_offset, m->nb_clusters << s->cluster_bits,
|
||||||
|
- QCOW2_DISCARD_NEVER);
|
||||||
|
+ if (!has_data_file(bs)) {
|
||||||
|
+ qcow2_free_clusters(bs, m->alloc_offset,
|
||||||
|
+ m->nb_clusters << s->cluster_bits,
|
||||||
|
+ QCOW2_DISCARD_NEVER);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
Name: qemu
|
Name: qemu
|
||||||
Version: 4.1.0
|
Version: 4.1.0
|
||||||
Release: 66
|
Release: 67
|
||||||
Epoch: 2
|
Epoch: 2
|
||||||
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
||||||
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
|
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
|
||||||
@ -384,6 +384,8 @@ Patch0371: iotests-143-Create-socket-in-SOCK_DIR.patch
|
|||||||
Patch0372: nbd-server-Avoid-long-error-message-assertions-CVE-2.patch
|
Patch0372: nbd-server-Avoid-long-error-message-assertions-CVE-2.patch
|
||||||
Patch0373: block-Call-attention-to-truncation-of-long-NBD-expor.patch
|
Patch0373: block-Call-attention-to-truncation-of-long-NBD-expor.patch
|
||||||
Patch0374: qemu-img-convert-Don-t-pre-zero-images.patch
|
Patch0374: qemu-img-convert-Don-t-pre-zero-images.patch
|
||||||
|
Patch0375: qcow2-Fix-qcow2_alloc_cluster_abort-for-external-dat.patch
|
||||||
|
Patch0376: mirror-Wait-only-for-in-flight-operations.patch
|
||||||
|
|
||||||
BuildRequires: flex
|
BuildRequires: flex
|
||||||
BuildRequires: gcc
|
BuildRequires: gcc
|
||||||
@ -778,6 +780,10 @@ getent passwd qemu >/dev/null || \
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Jul 22 2021 Chen Qun <kuhn.chenqun@huawei.com>
|
||||||
|
- qcow2: Fix qcow2_alloc_cluster_abort() for external data file
|
||||||
|
- mirror: Wait only for in-flight operations
|
||||||
|
|
||||||
* Wed Jul 21 2021 Chen Qun <kuhn.chenqun@huawei.com>
|
* Wed Jul 21 2021 Chen Qun <kuhn.chenqun@huawei.com>
|
||||||
- block/curl: HTTP header fields allow whitespace around values
|
- block/curl: HTTP header fields allow whitespace around values
|
||||||
- block/curl: HTTP header field names are case insensitive
|
- block/curl: HTTP header field names are case insensitive
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user