summaryrefslogtreecommitdiff
path: root/blockdev.c
diff options
context:
space:
mode:
authorJeff Cody <jcody@redhat.com>2014-06-25 15:40:11 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2014-07-01 10:47:01 +0200
commit13d8cc515dfcf5574077f964332d34890c0101d0 (patch)
tree04b5fa6227f8e9a199293c9e0b7e60ff2466d17f /blockdev.c
parent54e269009099cdc9483be115f1e12d56ad459c5e (diff)
downloadqemu-13d8cc515dfcf5574077f964332d34890c0101d0.tar.gz
block: add backing-file option to block-stream
On some image chains, QEMU may not always be able to resolve the filenames properly, when updating the backing file of an image after a block job. For instance, certain relative pathnames may fail, or drives may have been specified originally by file descriptor (e.g. /dev/fd/???), or a relative protocol pathname may have been used. In these instances, QEMU may lack the information to be able to make the correct choice, but the user or management layer most likely does have that knowledge. With this extension to the block-stream api, the user is able to change the backing file of the active layer as part of the block-stream operation. This allows the change to be 'safe', in the sense that if the attempt to write the active image metadata fails, then the block-stream operation returns failure, without disrupting the guest. If a backing file string is not specified in the command, the backing file string to use is determined in the same manner as it was previously. Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Jeff Cody <jcody@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'blockdev.c')
-rw-r--r--blockdev.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/blockdev.c b/blockdev.c
index 48315e86c0..48bd9a37bc 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1871,14 +1871,17 @@ static void block_job_cb(void *opaque, int ret)
bdrv_put_ref_bh_schedule(bs);
}
-void qmp_block_stream(const char *device, bool has_base,
- const char *base, bool has_speed, int64_t speed,
+void qmp_block_stream(const char *device,
+ bool has_base, const char *base,
+ bool has_backing_file, const char *backing_file,
+ bool has_speed, int64_t speed,
bool has_on_error, BlockdevOnError on_error,
Error **errp)
{
BlockDriverState *bs;
BlockDriverState *base_bs = NULL;
Error *local_err = NULL;
+ const char *base_name = NULL;
if (!has_on_error) {
on_error = BLOCKDEV_ON_ERROR_REPORT;
@@ -1894,15 +1897,27 @@ void qmp_block_stream(const char *device, bool has_base,
return;
}
- if (base) {
+ if (has_base) {
base_bs = bdrv_find_backing_image(bs, base);
if (base_bs == NULL) {
error_set(errp, QERR_BASE_NOT_FOUND, base);
return;
}
+ base_name = base;
}
- stream_start(bs, base_bs, base, has_speed ? speed : 0,
+ /* if we are streaming the entire chain, the result will have no backing
+ * file, and specifying one is therefore an error */
+ if (base_bs == NULL && has_backing_file) {
+ error_setg(errp, "backing file specified, but streaming the "
+ "entire chain");
+ return;
+ }
+
+ /* backing_file string overrides base bs filename */
+ base_name = has_backing_file ? backing_file : base_name;
+
+ stream_start(bs, base_bs, base_name, has_speed ? speed : 0,
on_error, block_job_cb, bs, &local_err);
if (local_err) {
error_propagate(errp, local_err);