thebeanogamer / rpms / qemu-kvm

Forked from rpms/qemu-kvm 5 months ago
Clone
7f1c5b
From b952c8f1da6f8597736c0e040565830139369359 Mon Sep 17 00:00:00 2001
7f1c5b
From: Stefano Garzarella <sgarzare@redhat.com>
7f1c5b
Date: Tue, 14 Feb 2023 18:16:21 +0100
7f1c5b
Subject: [PATCH] block: temporarily hold the new AioContext of bs_top in
7f1c5b
 bdrv_append()
7f1c5b
7f1c5b
RH-Author: Stefano Garzarella <sgarzare@redhat.com>
7f1c5b
RH-MergeRequest: 153: block: temporarily hold the new AioContext of bs_top in bdrv_append()
7f1c5b
RH-Bugzilla: 2168209
7f1c5b
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7f1c5b
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
7f1c5b
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
7f1c5b
RH-Commit: [1/1] 5b190426d996e8c9f7a781bd97aee8d25756dbd3 (sgarzarella/qemu-kvm-c-9-s)
7f1c5b
7f1c5b
bdrv_append() is called with bs_top AioContext held, but
7f1c5b
bdrv_attach_child_noperm() could change the AioContext of bs_top.
7f1c5b
7f1c5b
bdrv_replace_node_noperm() calls bdrv_drained_begin() starting from
7f1c5b
commit 2398747128 ("block: Don't poll in bdrv_replace_child_noperm()").
7f1c5b
bdrv_drained_begin() can call BDRV_POLL_WHILE that assumes the new lock
7f1c5b
is taken, so let's temporarily hold the new AioContext to prevent QEMU
7f1c5b
from failing in BDRV_POLL_WHILE when it tries to release the wrong
7f1c5b
AioContext.
7f1c5b
7f1c5b
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2168209
7f1c5b
Reported-by: Aihua Liang <aliang@redhat.com>
7f1c5b
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
7f1c5b
Message-Id: <20230214171621.11574-1-sgarzare@redhat.com>
7f1c5b
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7f1c5b
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7f1c5b
(cherry picked from commit 60d90bf43c169b9d1dbcb17ed794b7b02c6862b1)
7f1c5b
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
7f1c5b
---
7f1c5b
 block.c | 23 +++++++++++++++++++++++
7f1c5b
 1 file changed, 23 insertions(+)
7f1c5b
7f1c5b
diff --git a/block.c b/block.c
7f1c5b
index 0d78711416..9e1dcb9e47 100644
7f1c5b
--- a/block.c
7f1c5b
+++ b/block.c
7f1c5b
@@ -5275,6 +5275,8 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp)
7f1c5b
  * child.
7f1c5b
  *
7f1c5b
  * This function does not create any image files.
7f1c5b
+ *
7f1c5b
+ * The caller must hold the AioContext lock for @bs_top.
7f1c5b
  */
7f1c5b
 int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
7f1c5b
                 Error **errp)
7f1c5b
@@ -5282,11 +5284,14 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
7f1c5b
     int ret;
7f1c5b
     BdrvChild *child;
7f1c5b
     Transaction *tran = tran_new();
7f1c5b
+    AioContext *old_context, *new_context = NULL;
7f1c5b
 
7f1c5b
     GLOBAL_STATE_CODE();
7f1c5b
 
7f1c5b
     assert(!bs_new->backing);
7f1c5b
 
7f1c5b
+    old_context = bdrv_get_aio_context(bs_top);
7f1c5b
+
7f1c5b
     child = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
7f1c5b
                                      &child_of_bds, bdrv_backing_role(bs_new),
7f1c5b
                                      tran, errp);
7f1c5b
@@ -5295,6 +5300,19 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
7f1c5b
         goto out;
7f1c5b
     }
7f1c5b
 
7f1c5b
+    /*
7f1c5b
+     * bdrv_attach_child_noperm could change the AioContext of bs_top.
7f1c5b
+     * bdrv_replace_node_noperm calls bdrv_drained_begin, so let's temporarily
7f1c5b
+     * hold the new AioContext, since bdrv_drained_begin calls BDRV_POLL_WHILE
7f1c5b
+     * that assumes the new lock is taken.
7f1c5b
+     */
7f1c5b
+    new_context = bdrv_get_aio_context(bs_top);
7f1c5b
+
7f1c5b
+    if (old_context != new_context) {
7f1c5b
+        aio_context_release(old_context);
7f1c5b
+        aio_context_acquire(new_context);
7f1c5b
+    }
7f1c5b
+
7f1c5b
     ret = bdrv_replace_node_noperm(bs_top, bs_new, true, tran, errp);
7f1c5b
     if (ret < 0) {
7f1c5b
         goto out;
7f1c5b
@@ -5306,6 +5324,11 @@ out:
7f1c5b
 
7f1c5b
     bdrv_refresh_limits(bs_top, NULL, NULL);
7f1c5b
 
7f1c5b
+    if (new_context && old_context != new_context) {
7f1c5b
+        aio_context_release(new_context);
7f1c5b
+        aio_context_acquire(old_context);
7f1c5b
+    }
7f1c5b
+
7f1c5b
     return ret;
7f1c5b
 }
7f1c5b
 
7f1c5b
-- 
7f1c5b
2.31.1
7f1c5b