block: Fix AioContext locking in bdrv_open_inherit()
bdrv_open_inherit() calls several functions for which it needs to hold
the AioContext lock, but currently doesn't. This includes calls in
bdrv_append_temp_snapshot(), for which bdrv_open_inherit() is the only
caller. Fix the locking in these places.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20230605085711.21261-8-kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
diff --git a/block.c b/block.c
index 9800273..9815a6b 100644
--- a/block.c
+++ b/block.c
@@ -3794,6 +3794,7 @@
int64_t total_size;
QemuOpts *opts = NULL;
BlockDriverState *bs_snapshot = NULL;
+ AioContext *ctx = bdrv_get_aio_context(bs);
int ret;
GLOBAL_STATE_CODE();
@@ -3802,7 +3803,10 @@
instead of opening 'filename' directly */
/* Get the required size from the image */
+ aio_context_acquire(ctx);
total_size = bdrv_getlength(bs);
+ aio_context_release(ctx);
+
if (total_size < 0) {
error_setg_errno(errp, -total_size, "Could not get image size");
goto out;
@@ -3836,7 +3840,10 @@
goto out;
}
+ aio_context_acquire(ctx);
ret = bdrv_append(bs_snapshot, bs, errp);
+ aio_context_release(ctx);
+
if (ret < 0) {
bs_snapshot = NULL;
goto out;
@@ -3880,6 +3887,7 @@
Error *local_err = NULL;
QDict *snapshot_options = NULL;
int snapshot_flags = 0;
+ AioContext *ctx = qemu_get_aio_context();
assert(!child_class || !flags);
assert(!child_class == !parent);
@@ -4017,9 +4025,13 @@
/* Not requesting BLK_PERM_CONSISTENT_READ because we're only
* looking at the header to guess the image format. This works even
* in cases where a guest would not see a consistent state. */
- file = blk_new(bdrv_get_aio_context(file_bs), 0, BLK_PERM_ALL);
+ ctx = bdrv_get_aio_context(file_bs);
+ aio_context_acquire(ctx);
+ file = blk_new(ctx, 0, BLK_PERM_ALL);
blk_insert_bs(file, file_bs, &local_err);
bdrv_unref(file_bs);
+ aio_context_release(ctx);
+
if (local_err) {
goto fail;
}
@@ -4065,8 +4077,13 @@
goto fail;
}
+ /* The AioContext could have changed during bdrv_open_common() */
+ ctx = bdrv_get_aio_context(bs);
+
if (file) {
+ aio_context_acquire(ctx);
blk_unref(file);
+ aio_context_release(ctx);
file = NULL;
}
@@ -4124,13 +4141,16 @@
* (snapshot_bs); thus, we have to drop the strong reference to bs
* (which we obtained by calling bdrv_new()). bs will not be deleted,
* though, because the overlay still has a reference to it. */
+ aio_context_acquire(ctx);
bdrv_unref(bs);
+ aio_context_release(ctx);
bs = snapshot_bs;
}
return bs;
fail:
+ aio_context_acquire(ctx);
blk_unref(file);
qobject_unref(snapshot_options);
qobject_unref(bs->explicit_options);
@@ -4139,11 +4159,14 @@
bs->options = NULL;
bs->explicit_options = NULL;
bdrv_unref(bs);
+ aio_context_release(ctx);
error_propagate(errp, local_err);
return NULL;
close_and_fail:
+ aio_context_acquire(ctx);
bdrv_unref(bs);
+ aio_context_release(ctx);
qobject_unref(snapshot_options);
qobject_unref(options);
error_propagate(errp, local_err);