mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-12-18 05:28:36 -07:00
block: add QAPI command to allow live backing file change
This allows a user to make a live change to the backing file recorded in an open image. The image file to modify can be specified 2 ways: 1) image filename 2) image node-name Note: this does not cause the backing file itself to be reopened; it merely changes the backing filename in the image file structure, and in internal BDS structures. It is the responsibility of the user to pass a filename string that can be resolved when the image chain is reopened, and the filename string is not validated. A good analogy for this command is that it is a live version of 'qemu-img rebase -u', with respect to changing the backing file string. [Jeff is offline so I respun this patch in his absence. Dropped image filename since using node-name is preferred and this is a new command. No need to introduce the limitations of finding images by filename. --Stefan] Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Jeff Cody <jcody@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
4e855baabf
commit
fa40e65622
3 changed files with 144 additions and 0 deletions
79
blockdev.c
79
blockdev.c
|
|
@ -2367,6 +2367,85 @@ void qmp_block_job_complete(const char *device, Error **errp)
|
|||
block_job_complete(job, errp);
|
||||
}
|
||||
|
||||
void qmp_change_backing_file(const char *device,
|
||||
const char *image_node_name,
|
||||
const char *backing_file,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
BlockDriverState *image_bs = NULL;
|
||||
Error *local_err = NULL;
|
||||
bool ro;
|
||||
int open_flags;
|
||||
int ret;
|
||||
|
||||
/* find the top layer BDS of the chain */
|
||||
bs = bdrv_find(device);
|
||||
if (!bs) {
|
||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||
return;
|
||||
}
|
||||
|
||||
image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!image_bs) {
|
||||
error_setg(errp, "image file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bdrv_find_base(image_bs) == image_bs) {
|
||||
error_setg(errp, "not allowing backing file change on an image "
|
||||
"without a backing file");
|
||||
return;
|
||||
}
|
||||
|
||||
/* even though we are not necessarily operating on bs, we need it to
|
||||
* determine if block ops are currently prohibited on the chain */
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* final sanity check */
|
||||
if (!bdrv_chain_contains(bs, image_bs)) {
|
||||
error_setg(errp, "'%s' and image file are not in the same chain",
|
||||
device);
|
||||
return;
|
||||
}
|
||||
|
||||
/* if not r/w, reopen to make r/w */
|
||||
open_flags = image_bs->open_flags;
|
||||
ro = bdrv_is_read_only(image_bs);
|
||||
|
||||
if (ro) {
|
||||
bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ret = bdrv_change_backing_file(image_bs, backing_file,
|
||||
image_bs->drv ? image_bs->drv->format_name : "");
|
||||
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not change backing file to '%s'",
|
||||
backing_file);
|
||||
/* don't exit here, so we can try to restore open flags if
|
||||
* appropriate */
|
||||
}
|
||||
|
||||
if (ro) {
|
||||
bdrv_reopen(image_bs, open_flags, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err); /* will preserve prior errp */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue