mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00: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();
|
||||
|
|
|
@ -679,6 +679,32 @@
|
|||
{ 'command': 'blockdev-snapshot-sync',
|
||||
'data': 'BlockdevSnapshot' }
|
||||
|
||||
##
|
||||
# @change-backing-file
|
||||
#
|
||||
# Change the backing file in the image file metadata. This does not
|
||||
# cause QEMU to reopen the image file to reparse the backing filename
|
||||
# (it may, however, perform a reopen to change permissions from
|
||||
# r/o -> r/w -> r/o, if needed). The new backing file string is written
|
||||
# into the image file metadata, and the QEMU internal strings are
|
||||
# updated.
|
||||
#
|
||||
# @image-node-name: The name of the block driver state node of the
|
||||
# image to modify.
|
||||
#
|
||||
# @device: The name of the device that owns image-node-name.
|
||||
#
|
||||
# @backing-file: The string to write as the backing file. This
|
||||
# string is not validated, so care should be taken
|
||||
# when specifying the string or the image chain may
|
||||
# not be able to be reopened again.
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'command': 'change-backing-file',
|
||||
'data': { 'device': 'str', 'image-node-name': 'str',
|
||||
'backing-file': 'str' } }
|
||||
|
||||
##
|
||||
# @block-commit
|
||||
#
|
||||
|
|
|
@ -1350,6 +1350,45 @@ Example:
|
|||
"format": "qcow2" } }
|
||||
<- { "return": {} }
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
.name = "change-backing-file",
|
||||
.args_type = "device:s,image-node-name:s,backing-file:s",
|
||||
.mhandler.cmd_new = qmp_marshal_input_change_backing_file,
|
||||
},
|
||||
|
||||
SQMP
|
||||
change-backing-file
|
||||
-------------------
|
||||
Since: 2.1
|
||||
|
||||
Change the backing file in the image file metadata. This does not cause
|
||||
QEMU to reopen the image file to reparse the backing filename (it may,
|
||||
however, perform a reopen to change permissions from r/o -> r/w -> r/o,
|
||||
if needed). The new backing file string is written into the image file
|
||||
metadata, and the QEMU internal strings are updated.
|
||||
|
||||
Arguments:
|
||||
|
||||
- "image-node-name": The name of the block driver state node of the
|
||||
image to modify. The "device" is argument is used to
|
||||
verify "image-node-name" is in the chain described by
|
||||
"device".
|
||||
(json-string, optional)
|
||||
|
||||
- "device": The name of the device.
|
||||
(json-string)
|
||||
|
||||
- "backing-file": The string to write as the backing file. This string is
|
||||
not validated, so care should be taken when specifying
|
||||
the string or the image chain may not be able to be
|
||||
reopened again.
|
||||
(json-string)
|
||||
|
||||
Returns: Nothing on success
|
||||
If "device" does not exist or cannot be determined, DeviceNotFound
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue