|
|
9ae3a8 |
From 9482cf37df20d18140b24751972697f9349f1441 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Jeffrey Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
Date: Fri, 19 Sep 2014 03:18:58 +0200
|
|
|
9ae3a8 |
Subject: [PATCH 19/20] block: add backing-file option to block-stream
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Message-id: <5b8611fab581db6b4c5eb31c998378090819268d.1411096194.git.jcody@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 61312
|
|
|
9ae3a8 |
O-Subject: [PATCH qemu-kvm-rhev RHEL7.0.z 3/4] block: add backing-file option to block-stream
|
|
|
9ae3a8 |
Bugzilla: 1122925
|
|
|
9ae3a8 |
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
On some image chains, QEMU may not always be able to resolve the
|
|
|
9ae3a8 |
filenames properly, when updating the backing file of an image
|
|
|
9ae3a8 |
after a block job.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
For instance, certain relative pathnames may fail, or drives may
|
|
|
9ae3a8 |
have been specified originally by file descriptor (e.g. /dev/fd/???),
|
|
|
9ae3a8 |
or a relative protocol pathname may have been used.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
In these instances, QEMU may lack the information to be able to make
|
|
|
9ae3a8 |
the correct choice, but the user or management layer most likely does
|
|
|
9ae3a8 |
have that knowledge.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
With this extension to the block-stream api, the user is able to change
|
|
|
9ae3a8 |
the backing file of the active layer as part of the block-stream
|
|
|
9ae3a8 |
operation.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This allows the change to be 'safe', in the sense that if the attempt
|
|
|
9ae3a8 |
to write the active image metadata fails, then the block-stream
|
|
|
9ae3a8 |
operation returns failure, without disrupting the guest.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
If a backing file string is not specified in the command, the backing
|
|
|
9ae3a8 |
file string to use is determined in the same manner as it was
|
|
|
9ae3a8 |
previously.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Jeff Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
(cherry picked from commit 13d8cc515dfcf5574077f964332d34890c0101d0)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Conflicts:
|
|
|
9ae3a8 |
block/stream.c
|
|
|
9ae3a8 |
blockdev.c
|
|
|
9ae3a8 |
qapi/block-core.json
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RHEL7 Notes: Conflicts due to: surrounding context differences, and
|
|
|
9ae3a8 |
and the qapi json not being split into
|
|
|
9ae3a8 |
separate files like upstream. Also
|
|
|
9ae3a8 |
upstream used 1024 for local backing
|
|
|
9ae3a8 |
file string size, and downstream we
|
|
|
9ae3a8 |
already use PATH_MAX instead.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Jeff Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
block/stream.c | 11 +++++------
|
|
|
9ae3a8 |
blockdev.c | 23 +++++++++++++++++++----
|
|
|
9ae3a8 |
hmp.c | 2 +-
|
|
|
9ae3a8 |
qapi-schema.json | 19 +++++++++++++++++--
|
|
|
9ae3a8 |
qmp-commands.hx | 2 +-
|
|
|
9ae3a8 |
5 files changed, 43 insertions(+), 14 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/block/stream.c b/block/stream.c
|
|
|
9ae3a8 |
index 2a6f533..367120d 100644
|
|
|
9ae3a8 |
--- a/block/stream.c
|
|
|
9ae3a8 |
+++ b/block/stream.c
|
|
|
9ae3a8 |
@@ -32,7 +32,7 @@ typedef struct StreamBlockJob {
|
|
|
9ae3a8 |
RateLimit limit;
|
|
|
9ae3a8 |
BlockDriverState *base;
|
|
|
9ae3a8 |
BlockdevOnError on_error;
|
|
|
9ae3a8 |
- char backing_file_id[PATH_MAX];
|
|
|
9ae3a8 |
+ char *backing_file_str;
|
|
|
9ae3a8 |
} StreamBlockJob;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
static int coroutine_fn stream_populate(BlockDriverState *bs,
|
|
|
9ae3a8 |
@@ -182,7 +182,7 @@ wait:
|
|
|
9ae3a8 |
if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) {
|
|
|
9ae3a8 |
const char *base_id = NULL, *base_fmt = NULL;
|
|
|
9ae3a8 |
if (base) {
|
|
|
9ae3a8 |
- base_id = s->backing_file_id;
|
|
|
9ae3a8 |
+ base_id = s->backing_file_str;
|
|
|
9ae3a8 |
if (base->drv) {
|
|
|
9ae3a8 |
base_fmt = base->drv->format_name;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
@@ -192,6 +192,7 @@ wait:
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
qemu_vfree(buf);
|
|
|
9ae3a8 |
+ g_free(s->backing_file_str);
|
|
|
9ae3a8 |
block_job_completed(&s->common, ret);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
@@ -213,7 +214,7 @@ static const BlockJobDriver stream_job_driver = {
|
|
|
9ae3a8 |
};
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
void stream_start(BlockDriverState *bs, BlockDriverState *base,
|
|
|
9ae3a8 |
- const char *base_id, int64_t speed,
|
|
|
9ae3a8 |
+ const char *backing_file_str, int64_t speed,
|
|
|
9ae3a8 |
BlockdevOnError on_error,
|
|
|
9ae3a8 |
BlockDriverCompletionFunc *cb,
|
|
|
9ae3a8 |
void *opaque, Error **errp)
|
|
|
9ae3a8 |
@@ -233,9 +234,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
s->base = base;
|
|
|
9ae3a8 |
- if (base_id) {
|
|
|
9ae3a8 |
- pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id);
|
|
|
9ae3a8 |
- }
|
|
|
9ae3a8 |
+ s->backing_file_str = g_strdup(backing_file_str);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
s->on_error = on_error;
|
|
|
9ae3a8 |
s->common.co = qemu_coroutine_create(stream_run);
|
|
|
9ae3a8 |
diff --git a/blockdev.c b/blockdev.c
|
|
|
9ae3a8 |
index 96dc3df..09ef3f7 100644
|
|
|
9ae3a8 |
--- a/blockdev.c
|
|
|
9ae3a8 |
+++ b/blockdev.c
|
|
|
9ae3a8 |
@@ -1425,14 +1425,17 @@ static void block_job_cb(void *opaque, int ret)
|
|
|
9ae3a8 |
bdrv_put_ref_bh_schedule(bs);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
-void qmp_block_stream(const char *device, bool has_base,
|
|
|
9ae3a8 |
- const char *base, bool has_speed, int64_t speed,
|
|
|
9ae3a8 |
+void qmp_block_stream(const char *device,
|
|
|
9ae3a8 |
+ bool has_base, const char *base,
|
|
|
9ae3a8 |
+ bool has_backing_file, const char *backing_file,
|
|
|
9ae3a8 |
+ bool has_speed, int64_t speed,
|
|
|
9ae3a8 |
bool has_on_error, BlockdevOnError on_error,
|
|
|
9ae3a8 |
Error **errp)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
BlockDriverState *bs;
|
|
|
9ae3a8 |
BlockDriverState *base_bs = NULL;
|
|
|
9ae3a8 |
Error *local_err = NULL;
|
|
|
9ae3a8 |
+ const char *base_name = NULL;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
if (!has_on_error) {
|
|
|
9ae3a8 |
on_error = BLOCKDEV_ON_ERROR_REPORT;
|
|
|
9ae3a8 |
@@ -1444,15 +1447,27 @@ void qmp_block_stream(const char *device, bool has_base,
|
|
|
9ae3a8 |
return;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
- if (base) {
|
|
|
9ae3a8 |
+ if (has_base) {
|
|
|
9ae3a8 |
base_bs = bdrv_find_backing_image(bs, base);
|
|
|
9ae3a8 |
if (base_bs == NULL) {
|
|
|
9ae3a8 |
error_set(errp, QERR_BASE_NOT_FOUND, base);
|
|
|
9ae3a8 |
return;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ base_name = base;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
- stream_start(bs, base_bs, base, has_speed ? speed : 0,
|
|
|
9ae3a8 |
+ /* if we are streaming the entire chain, the result will have no backing
|
|
|
9ae3a8 |
+ * file, and specifying one is therefore an error */
|
|
|
9ae3a8 |
+ if (base_bs == NULL && has_backing_file) {
|
|
|
9ae3a8 |
+ error_setg(errp, "backing file specified, but streaming the "
|
|
|
9ae3a8 |
+ "entire chain");
|
|
|
9ae3a8 |
+ return;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ /* backing_file string overrides base bs filename */
|
|
|
9ae3a8 |
+ base_name = has_backing_file ? backing_file : base_name;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ stream_start(bs, base_bs, base_name, has_speed ? speed : 0,
|
|
|
9ae3a8 |
on_error, block_job_cb, bs, &local_err);
|
|
|
9ae3a8 |
if (error_is_set(&local_err)) {
|
|
|
9ae3a8 |
error_propagate(errp, local_err);
|
|
|
9ae3a8 |
diff --git a/hmp.c b/hmp.c
|
|
|
9ae3a8 |
index 841929d..b723b26 100644
|
|
|
9ae3a8 |
--- a/hmp.c
|
|
|
9ae3a8 |
+++ b/hmp.c
|
|
|
9ae3a8 |
@@ -1046,7 +1046,7 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
|
|
|
9ae3a8 |
const char *base = qdict_get_try_str(qdict, "base");
|
|
|
9ae3a8 |
int64_t speed = qdict_get_try_int(qdict, "speed", 0);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
- qmp_block_stream(device, base != NULL, base,
|
|
|
9ae3a8 |
+ qmp_block_stream(device, base != NULL, base, false, NULL,
|
|
|
9ae3a8 |
qdict_haskey(qdict, "speed"), speed,
|
|
|
9ae3a8 |
BLOCKDEV_ON_ERROR_REPORT, true, &error);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/qapi-schema.json b/qapi-schema.json
|
|
|
9ae3a8 |
index ed79eb9..40bd2a6 100644
|
|
|
9ae3a8 |
--- a/qapi-schema.json
|
|
|
9ae3a8 |
+++ b/qapi-schema.json
|
|
|
9ae3a8 |
@@ -2280,6 +2280,21 @@
|
|
|
9ae3a8 |
#
|
|
|
9ae3a8 |
# @base: #optional the common backing file name
|
|
|
9ae3a8 |
#
|
|
|
9ae3a8 |
+# @backing-file: #optional The backing file string to write into the active
|
|
|
9ae3a8 |
+# layer. This filename is not validated.
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
+# If a pathname string is such that it cannot be
|
|
|
9ae3a8 |
+# resolved by QEMU, that means that subsequent QMP or
|
|
|
9ae3a8 |
+# HMP commands must use node-names for the image in
|
|
|
9ae3a8 |
+# question, as filename lookup methods will fail.
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
+# If not specified, QEMU will automatically determine
|
|
|
9ae3a8 |
+# the backing file string to use, or error out if there
|
|
|
9ae3a8 |
+# is no obvious choice. Care should be taken when
|
|
|
9ae3a8 |
+# specifying the string, to specify a valid filename or
|
|
|
9ae3a8 |
+# protocol.
|
|
|
9ae3a8 |
+# (Since 2.1)
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
# @speed: #optional the maximum speed, in bytes per second
|
|
|
9ae3a8 |
#
|
|
|
9ae3a8 |
# @on-error: #optional the action to take on an error (default report).
|
|
|
9ae3a8 |
@@ -2292,8 +2307,8 @@
|
|
|
9ae3a8 |
# Since: 1.1
|
|
|
9ae3a8 |
##
|
|
|
9ae3a8 |
{ 'command': 'block-stream',
|
|
|
9ae3a8 |
- 'data': { 'device': 'str', '*base': 'str', '*speed': 'int',
|
|
|
9ae3a8 |
- '*on-error': 'BlockdevOnError' } }
|
|
|
9ae3a8 |
+ 'data': { 'device': 'str', '*base': 'str', '*backing-file': 'str',
|
|
|
9ae3a8 |
+ '*speed': 'int', '*on-error': 'BlockdevOnError' } }
|
|
|
9ae3a8 |
#_end-rhev-only
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
##
|
|
|
9ae3a8 |
diff --git a/qmp-commands.hx b/qmp-commands.hx
|
|
|
9ae3a8 |
index 5ece4f9..c07cf8a 100644
|
|
|
9ae3a8 |
--- a/qmp-commands.hx
|
|
|
9ae3a8 |
+++ b/qmp-commands.hx
|
|
|
9ae3a8 |
@@ -999,7 +999,7 @@ EQMP
|
|
|
9ae3a8 |
#ifdef CONFIG_LIVE_BLOCK_OPS
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
.name = "block-stream",
|
|
|
9ae3a8 |
- .args_type = "device:B,base:s?,speed:o?,on-error:s?",
|
|
|
9ae3a8 |
+ .args_type = "device:B,base:s?,speed:o?,backing-file:s?,on-error:s?",
|
|
|
9ae3a8 |
.mhandler.cmd_new = qmp_marshal_input_block_stream,
|
|
|
9ae3a8 |
},
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|