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>
This commit is contained in:
parent
4b408668d0
commit
f665f01f72
25
block.c
25
block.c
|
@ -3794,6 +3794,7 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
||||||
int64_t total_size;
|
int64_t total_size;
|
||||||
QemuOpts *opts = NULL;
|
QemuOpts *opts = NULL;
|
||||||
BlockDriverState *bs_snapshot = NULL;
|
BlockDriverState *bs_snapshot = NULL;
|
||||||
|
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
|
@ -3802,7 +3803,10 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
||||||
instead of opening 'filename' directly */
|
instead of opening 'filename' directly */
|
||||||
|
|
||||||
/* Get the required size from the image */
|
/* Get the required size from the image */
|
||||||
|
aio_context_acquire(ctx);
|
||||||
total_size = bdrv_getlength(bs);
|
total_size = bdrv_getlength(bs);
|
||||||
|
aio_context_release(ctx);
|
||||||
|
|
||||||
if (total_size < 0) {
|
if (total_size < 0) {
|
||||||
error_setg_errno(errp, -total_size, "Could not get image size");
|
error_setg_errno(errp, -total_size, "Could not get image size");
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -3836,7 +3840,10 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
ret = bdrv_append(bs_snapshot, bs, errp);
|
ret = bdrv_append(bs_snapshot, bs, errp);
|
||||||
|
aio_context_release(ctx);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bs_snapshot = NULL;
|
bs_snapshot = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -3880,6 +3887,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
QDict *snapshot_options = NULL;
|
QDict *snapshot_options = NULL;
|
||||||
int snapshot_flags = 0;
|
int snapshot_flags = 0;
|
||||||
|
AioContext *ctx = qemu_get_aio_context();
|
||||||
|
|
||||||
assert(!child_class || !flags);
|
assert(!child_class || !flags);
|
||||||
assert(!child_class == !parent);
|
assert(!child_class == !parent);
|
||||||
|
@ -4017,9 +4025,13 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
/* Not requesting BLK_PERM_CONSISTENT_READ because we're only
|
/* Not requesting BLK_PERM_CONSISTENT_READ because we're only
|
||||||
* looking at the header to guess the image format. This works even
|
* looking at the header to guess the image format. This works even
|
||||||
* in cases where a guest would not see a consistent state. */
|
* 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);
|
blk_insert_bs(file, file_bs, &local_err);
|
||||||
bdrv_unref(file_bs);
|
bdrv_unref(file_bs);
|
||||||
|
aio_context_release(ctx);
|
||||||
|
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -4065,8 +4077,13 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The AioContext could have changed during bdrv_open_common() */
|
||||||
|
ctx = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
|
aio_context_acquire(ctx);
|
||||||
blk_unref(file);
|
blk_unref(file);
|
||||||
|
aio_context_release(ctx);
|
||||||
file = NULL;
|
file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4124,13 +4141,16 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
* (snapshot_bs); thus, we have to drop the strong reference to bs
|
* (snapshot_bs); thus, we have to drop the strong reference to bs
|
||||||
* (which we obtained by calling bdrv_new()). bs will not be deleted,
|
* (which we obtained by calling bdrv_new()). bs will not be deleted,
|
||||||
* though, because the overlay still has a reference to it. */
|
* though, because the overlay still has a reference to it. */
|
||||||
|
aio_context_acquire(ctx);
|
||||||
bdrv_unref(bs);
|
bdrv_unref(bs);
|
||||||
|
aio_context_release(ctx);
|
||||||
bs = snapshot_bs;
|
bs = snapshot_bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bs;
|
return bs;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
aio_context_acquire(ctx);
|
||||||
blk_unref(file);
|
blk_unref(file);
|
||||||
qobject_unref(snapshot_options);
|
qobject_unref(snapshot_options);
|
||||||
qobject_unref(bs->explicit_options);
|
qobject_unref(bs->explicit_options);
|
||||||
|
@ -4139,11 +4159,14 @@ fail:
|
||||||
bs->options = NULL;
|
bs->options = NULL;
|
||||||
bs->explicit_options = NULL;
|
bs->explicit_options = NULL;
|
||||||
bdrv_unref(bs);
|
bdrv_unref(bs);
|
||||||
|
aio_context_release(ctx);
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
close_and_fail:
|
close_and_fail:
|
||||||
|
aio_context_acquire(ctx);
|
||||||
bdrv_unref(bs);
|
bdrv_unref(bs);
|
||||||
|
aio_context_release(ctx);
|
||||||
qobject_unref(snapshot_options);
|
qobject_unref(snapshot_options);
|
||||||
qobject_unref(options);
|
qobject_unref(options);
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
|
Loading…
Reference in New Issue