97 lines
3.4 KiB
Diff
97 lines
3.4 KiB
Diff
From 0db52fa2553ba83454a347e0aca4896e1b0d9b41 Mon Sep 17 00:00:00 2001
|
|
From: Sergio Lopez Pascual <slp@redhat.com>
|
|
Date: Thu, 11 Feb 2021 14:42:06 -0300
|
|
Subject: [PATCH 4/6] block: Avoid processing BDS twice in
|
|
bdrv_set_aio_context_ignore()
|
|
|
|
RH-Author: Sergio Lopez Pascual <slp@redhat.com>
|
|
Message-id: <20210211144208.58930-4-slp@redhat.com>
|
|
Patchwork-id: 101050
|
|
O-Subject: [RHEL-AV-8.4.0 qemu-kvm PATCH 3/5] block: Avoid processing BDS twice in bdrv_set_aio_context_ignore()
|
|
Bugzilla: 1918966 1918968
|
|
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
|
|
Some graphs may contain an indirect reference to the first BDS in the
|
|
chain that can be reached while walking it bottom->up from one its
|
|
children.
|
|
|
|
Doubling-processing of a BDS is especially problematic for the
|
|
aio_notifiers, as they might attempt to work on both the old and the
|
|
new AIO contexts.
|
|
|
|
To avoid this problem, add every child and parent to the ignore list
|
|
before actually processing them.
|
|
|
|
Suggested-by: Kevin Wolf <kwolf@redhat.com>
|
|
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
|
Message-Id: <20210201125032.44713-2-slp@redhat.com>
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
(cherry picked from commit 722d8e73d65cb54f39d360ecb2147ac58f43c399)
|
|
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
|
Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
|
|
---
|
|
block.c | 34 +++++++++++++++++++++++++++-------
|
|
1 file changed, 27 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/block.c b/block.c
|
|
index f1cedac362..8bfa446f9c 100644
|
|
--- a/block.c
|
|
+++ b/block.c
|
|
@@ -6454,7 +6454,10 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
|
|
AioContext *new_context, GSList **ignore)
|
|
{
|
|
AioContext *old_context = bdrv_get_aio_context(bs);
|
|
- BdrvChild *child;
|
|
+ GSList *children_to_process = NULL;
|
|
+ GSList *parents_to_process = NULL;
|
|
+ GSList *entry;
|
|
+ BdrvChild *child, *parent;
|
|
|
|
g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
|
|
|
@@ -6469,16 +6472,33 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
|
|
continue;
|
|
}
|
|
*ignore = g_slist_prepend(*ignore, child);
|
|
- bdrv_set_aio_context_ignore(child->bs, new_context, ignore);
|
|
+ children_to_process = g_slist_prepend(children_to_process, child);
|
|
}
|
|
- QLIST_FOREACH(child, &bs->parents, next_parent) {
|
|
- if (g_slist_find(*ignore, child)) {
|
|
+
|
|
+ QLIST_FOREACH(parent, &bs->parents, next_parent) {
|
|
+ if (g_slist_find(*ignore, parent)) {
|
|
continue;
|
|
}
|
|
- assert(child->klass->set_aio_ctx);
|
|
- *ignore = g_slist_prepend(*ignore, child);
|
|
- child->klass->set_aio_ctx(child, new_context, ignore);
|
|
+ *ignore = g_slist_prepend(*ignore, parent);
|
|
+ parents_to_process = g_slist_prepend(parents_to_process, parent);
|
|
+ }
|
|
+
|
|
+ for (entry = children_to_process;
|
|
+ entry != NULL;
|
|
+ entry = g_slist_next(entry)) {
|
|
+ child = entry->data;
|
|
+ bdrv_set_aio_context_ignore(child->bs, new_context, ignore);
|
|
+ }
|
|
+ g_slist_free(children_to_process);
|
|
+
|
|
+ for (entry = parents_to_process;
|
|
+ entry != NULL;
|
|
+ entry = g_slist_next(entry)) {
|
|
+ parent = entry->data;
|
|
+ assert(parent->klass->set_aio_ctx);
|
|
+ parent->klass->set_aio_ctx(parent, new_context, ignore);
|
|
}
|
|
+ g_slist_free(parents_to_process);
|
|
|
|
bdrv_detach_aio_context(bs);
|
|
|
|
--
|
|
2.27.0
|
|
|