qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 29/36] blockdev: qmp_x_blockdev_reopen: acquire all contexts


From: Vladimir Sementsov-Ogievskiy
Subject: [PATCH v2 29/36] blockdev: qmp_x_blockdev_reopen: acquire all contexts
Date: Fri, 27 Nov 2020 17:45:15 +0300

During reopen we may add backing bs from other aio context, which may
lead to changing original context of top bs.

We are going to move graph modification to prepare stage. So, it will
be possible that bdrv_flush() in bdrv_reopen_prepare called on bs in
non-original aio context, which we didn't aquire which leads to crash.

More correct would be to acquire all aio context we are going to work
with. And the simplest ways is to just acquire all of them. It may be
optimized later if needed.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
 blockdev.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 2af35d0958..098a05709d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3531,7 +3531,6 @@ fail:
 void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp)
 {
     BlockDriverState *bs;
-    AioContext *ctx;
     QObject *obj;
     Visitor *v = qobject_output_visitor_new(&obj);
     BlockReopenQueue *queue;
@@ -3557,13 +3556,29 @@ void qmp_x_blockdev_reopen(BlockdevOptions *options, 
Error **errp)
     qdict_flatten(qdict);
 
     /* Perform the reopen operation */
-    ctx = bdrv_get_aio_context(bs);
-    aio_context_acquire(ctx);
+    BdrvNextIterator it;
+    GSList *aio_ctxs = NULL, *ctx;
+    BlockDriverState *it_bs;
+
+    for (it_bs = bdrv_first(&it); it_bs; it_bs = bdrv_next(&it)) {
+        AioContext *aio_context = bdrv_get_aio_context(it_bs);
+
+        if (!g_slist_find(aio_ctxs, aio_context)) {
+            aio_ctxs = g_slist_prepend(aio_ctxs, aio_context);
+            aio_context_acquire(aio_context);
+        }
+    }
+
     bdrv_subtree_drained_begin(bs);
     queue = bdrv_reopen_queue(NULL, bs, qdict, false);
     bdrv_reopen_multiple(queue, errp);
     bdrv_subtree_drained_end(bs);
-    aio_context_release(ctx);
+
+    for (ctx = aio_ctxs; ctx != NULL; ctx = ctx->next) {
+        AioContext *aio_context = ctx->data;
+        aio_context_release(aio_context);
+    }
+    g_slist_free(aio_ctxs);
 
 fail:
     visit_free(v);
-- 
2.21.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]