aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2023-05-25 14:47:11 +0200
committerKevin Wolf <kwolf@redhat.com>2023-05-30 17:29:44 +0200
commit8823407c06a920eb2af217660094fdd8aff6c176 (patch)
tree67251c7c3e1d3d283f83af4de82db03a023c11ca /block.c
parent8dc8a60c9e52fa446a5135180592c0cd4213acfb (diff)
downloadqemu-8823407c06a920eb2af217660094fdd8aff6c176.zip
qemu-8823407c06a920eb2af217660094fdd8aff6c176.tar.gz
qemu-8823407c06a920eb2af217660094fdd8aff6c176.tar.bz2
block: Fix AioContext locking in bdrv_insert_node()
While calling bdrv_new_open_driver_opts(), the main AioContext lock must be held, not the lock of the AioContext of the block subtree it will be added to afterwards. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Message-Id: <20230525124713.401149-11-kwolf@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block.c')
-rw-r--r--block.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/block.c b/block.c
index 29dea3a..ec65fcf 100644
--- a/block.c
+++ b/block.c
@@ -5399,12 +5399,17 @@ static void bdrv_delete(BlockDriverState *bs)
* empty set of options. The reference to the QDict belongs to the block layer
* after the call (even on failure), so if the caller intends to reuse the
* dictionary, it needs to use qobject_ref() before calling bdrv_open.
+ *
+ * The caller holds the AioContext lock for @bs. It must make sure that @bs
+ * stays in the same AioContext, i.e. @options must not refer to nodes in a
+ * different AioContext.
*/
BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
int flags, Error **errp)
{
ERRP_GUARD();
int ret;
+ AioContext *ctx = bdrv_get_aio_context(bs);
BlockDriverState *new_node_bs = NULL;
const char *drvname, *node_name;
BlockDriver *drv;
@@ -5425,8 +5430,14 @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
GLOBAL_STATE_CODE();
+ aio_context_release(ctx);
+ aio_context_acquire(qemu_get_aio_context());
new_node_bs = bdrv_new_open_driver_opts(drv, node_name, options, flags,
errp);
+ aio_context_release(qemu_get_aio_context());
+ aio_context_acquire(ctx);
+ assert(bdrv_get_aio_context(bs) == ctx);
+
options = NULL; /* bdrv_new_open_driver() eats options */
if (!new_node_bs) {
error_prepend(errp, "Could not create node: ");