mirror of https://github.com/xemu-project/xemu.git
blockdev: acquire AioContext in change-backing-file
Add dataplane support to the change-backing-file QMP commands. By acquiring the AioContext we avoid race conditions with the dataplane thread which may also be accessing the BlockDriverState. Note that this command operates on both bs and a node in its chain (image_bs). The bdrv_chain_contains(bs, image_bs) check guarantees that bs and image_bs are in the same AioContext. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
e3442099a2
commit
729962f6db
19
blockdev.c
19
blockdev.c
|
@ -2584,6 +2584,7 @@ void qmp_change_backing_file(const char *device,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
|
AioContext *aio_context;
|
||||||
BlockDriverState *image_bs = NULL;
|
BlockDriverState *image_bs = NULL;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
bool ro;
|
bool ro;
|
||||||
|
@ -2597,34 +2598,37 @@ void qmp_change_backing_file(const char *device,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err);
|
image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!image_bs) {
|
if (!image_bs) {
|
||||||
error_setg(errp, "image file not found");
|
error_setg(errp, "image file not found");
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_find_base(image_bs) == image_bs) {
|
if (bdrv_find_base(image_bs) == image_bs) {
|
||||||
error_setg(errp, "not allowing backing file change on an image "
|
error_setg(errp, "not allowing backing file change on an image "
|
||||||
"without a backing file");
|
"without a backing file");
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* even though we are not necessarily operating on bs, we need it to
|
/* even though we are not necessarily operating on bs, we need it to
|
||||||
* determine if block ops are currently prohibited on the chain */
|
* determine if block ops are currently prohibited on the chain */
|
||||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) {
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* final sanity check */
|
/* final sanity check */
|
||||||
if (!bdrv_chain_contains(bs, image_bs)) {
|
if (!bdrv_chain_contains(bs, image_bs)) {
|
||||||
error_setg(errp, "'%s' and image file are not in the same chain",
|
error_setg(errp, "'%s' and image file are not in the same chain",
|
||||||
device);
|
device);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if not r/w, reopen to make r/w */
|
/* if not r/w, reopen to make r/w */
|
||||||
|
@ -2635,7 +2639,7 @@ void qmp_change_backing_file(const char *device,
|
||||||
bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err);
|
bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2655,6 +2659,9 @@ void qmp_change_backing_file(const char *device,
|
||||||
error_propagate(errp, local_err); /* will preserve prior errp */
|
error_propagate(errp, local_err); /* will preserve prior errp */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||||
|
|
|
@ -197,6 +197,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
|
||||||
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT, s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
|
||||||
|
|
Loading…
Reference in New Issue