|
|
9ae3a8 |
From 820c45fa40b9763a207e9eeb1268f87c2ac06351 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Jeffrey Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
Date: Fri, 19 Sep 2014 03:18:57 +0200
|
|
|
9ae3a8 |
Subject: [PATCH 18/20] block: extend block-commit to accept a string for the backing file
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Message-id: <d49dacc368c02a3cd3d3d9b1d7ea0dc75cc7884a.1411096194.git.jcody@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 61311
|
|
|
9ae3a8 |
O-Subject: [PATCH qemu-kvm-rhev RHEL7.0.z 2/4] block: extend block-commit to accept a string for the backing file
|
|
|
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 commit.
|
|
|
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-commit api, the user is able to change
|
|
|
9ae3a8 |
the backing file of the overlay image as part of the block-commit
|
|
|
9ae3a8 |
operation.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This allows the change to be 'safe', in the sense that if the attempt
|
|
|
9ae3a8 |
to write the overlay image metadata fails, then the block-commit
|
|
|
9ae3a8 |
operation returns failure, without disrupting the guest.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
If the commit top is the active layer, then specifying the backing
|
|
|
9ae3a8 |
file string will be treated as an error (there is no overlay image
|
|
|
9ae3a8 |
to modify in that case).
|
|
|
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 |
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
(cherry picked from commit 54e269009099cdc9483be115f1e12d56ad459c5e)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Conflicts:
|
|
|
9ae3a8 |
qapi/block-core.json
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RHEL7 Notes: Conflict is due to qapi json being divided into separate
|
|
|
9ae3a8 |
files upstream; downstream in RHEL7 it is still in a single
|
|
|
9ae3a8 |
json file.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Jeff Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
block.c | 8 ++++++--
|
|
|
9ae3a8 |
block/commit.c | 9 ++++++---
|
|
|
9ae3a8 |
blockdev.c | 8 +++++++-
|
|
|
9ae3a8 |
include/block/block.h | 3 ++-
|
|
|
9ae3a8 |
include/block/block_int.h | 3 ++-
|
|
|
9ae3a8 |
qapi-schema.json | 20 ++++++++++++++++++--
|
|
|
9ae3a8 |
qmp-commands.hx | 19 ++++++++++++++++++-
|
|
|
9ae3a8 |
7 files changed, 59 insertions(+), 11 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/block.c b/block.c
|
|
|
9ae3a8 |
index 7bdbbc6..496eb72 100644
|
|
|
9ae3a8 |
--- a/block.c
|
|
|
9ae3a8 |
+++ b/block.c
|
|
|
9ae3a8 |
@@ -2323,12 +2323,15 @@ typedef struct BlkIntermediateStates {
|
|
|
9ae3a8 |
*
|
|
|
9ae3a8 |
* base <- active
|
|
|
9ae3a8 |
*
|
|
|
9ae3a8 |
+ * If backing_file_str is non-NULL, it will be used when modifying top's
|
|
|
9ae3a8 |
+ * overlay image metadata.
|
|
|
9ae3a8 |
+ *
|
|
|
9ae3a8 |
* Error conditions:
|
|
|
9ae3a8 |
* if active == top, that is considered an error
|
|
|
9ae3a8 |
*
|
|
|
9ae3a8 |
*/
|
|
|
9ae3a8 |
int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
|
|
|
9ae3a8 |
- BlockDriverState *base)
|
|
|
9ae3a8 |
+ BlockDriverState *base, const char *backing_file_str)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
BlockDriverState *intermediate;
|
|
|
9ae3a8 |
BlockDriverState *base_bs = NULL;
|
|
|
9ae3a8 |
@@ -2380,7 +2383,8 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
/* success - we can delete the intermediate states, and link top->base */
|
|
|
9ae3a8 |
- ret = bdrv_change_backing_file(new_top_bs, base_bs->filename,
|
|
|
9ae3a8 |
+ backing_file_str = backing_file_str ? backing_file_str : base_bs->filename;
|
|
|
9ae3a8 |
+ ret = bdrv_change_backing_file(new_top_bs, backing_file_str,
|
|
|
9ae3a8 |
base_bs->drv ? base_bs->drv->format_name : "");
|
|
|
9ae3a8 |
if (ret) {
|
|
|
9ae3a8 |
goto exit;
|
|
|
9ae3a8 |
diff --git a/block/commit.c b/block/commit.c
|
|
|
9ae3a8 |
index e3e395d..b6e1770 100644
|
|
|
9ae3a8 |
--- a/block/commit.c
|
|
|
9ae3a8 |
+++ b/block/commit.c
|
|
|
9ae3a8 |
@@ -37,6 +37,7 @@ typedef struct CommitBlockJob {
|
|
|
9ae3a8 |
BlockdevOnError on_error;
|
|
|
9ae3a8 |
int base_flags;
|
|
|
9ae3a8 |
int orig_overlay_flags;
|
|
|
9ae3a8 |
+ char *backing_file_str;
|
|
|
9ae3a8 |
} CommitBlockJob;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
static int coroutine_fn commit_populate(BlockDriverState *bs,
|
|
|
9ae3a8 |
@@ -141,7 +142,7 @@ wait:
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
if (!block_job_is_cancelled(&s->common) && sector_num == end) {
|
|
|
9ae3a8 |
/* success */
|
|
|
9ae3a8 |
- ret = bdrv_drop_intermediate(active, top, base);
|
|
|
9ae3a8 |
+ ret = bdrv_drop_intermediate(active, top, base, s->backing_file_str);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
exit_free_buf:
|
|
|
9ae3a8 |
@@ -158,7 +159,7 @@ exit_restore_reopen:
|
|
|
9ae3a8 |
if (overlay_bs && s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) {
|
|
|
9ae3a8 |
bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
-
|
|
|
9ae3a8 |
+ g_free(s->backing_file_str);
|
|
|
9ae3a8 |
block_job_completed(&s->common, ret);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
@@ -182,7 +183,7 @@ static const BlockJobDriver commit_job_driver = {
|
|
|
9ae3a8 |
void commit_start(BlockDriverState *bs, BlockDriverState *base,
|
|
|
9ae3a8 |
BlockDriverState *top, int64_t speed,
|
|
|
9ae3a8 |
BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
|
|
|
9ae3a8 |
- void *opaque, Error **errp)
|
|
|
9ae3a8 |
+ void *opaque, const char *backing_file_str, Error **errp)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
CommitBlockJob *s;
|
|
|
9ae3a8 |
BlockReopenQueue *reopen_queue = NULL;
|
|
|
9ae3a8 |
@@ -244,6 +245,8 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
|
|
|
9ae3a8 |
s->base_flags = orig_base_flags;
|
|
|
9ae3a8 |
s->orig_overlay_flags = orig_overlay_flags;
|
|
|
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(commit_run);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/blockdev.c b/blockdev.c
|
|
|
9ae3a8 |
index 107e27e..96dc3df 100644
|
|
|
9ae3a8 |
--- a/blockdev.c
|
|
|
9ae3a8 |
+++ b/blockdev.c
|
|
|
9ae3a8 |
@@ -1465,6 +1465,7 @@ void qmp_block_stream(const char *device, bool has_base,
|
|
|
9ae3a8 |
void qmp_block_commit(const char *device,
|
|
|
9ae3a8 |
bool has_base, const char *base,
|
|
|
9ae3a8 |
bool has_top, const char *top,
|
|
|
9ae3a8 |
+ bool has_backing_file, const char *backing_file,
|
|
|
9ae3a8 |
bool has_speed, int64_t speed,
|
|
|
9ae3a8 |
Error **errp)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
@@ -1522,11 +1523,16 @@ void qmp_block_commit(const char *device,
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
if (top_bs == bs) {
|
|
|
9ae3a8 |
+ if (has_backing_file) {
|
|
|
9ae3a8 |
+ error_setg(errp, "'backing-file' specified,"
|
|
|
9ae3a8 |
+ " but 'top' is the active layer");
|
|
|
9ae3a8 |
+ return;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
commit_active_start(bs, base_bs, speed, on_error, block_job_cb,
|
|
|
9ae3a8 |
bs, &local_err);
|
|
|
9ae3a8 |
} else {
|
|
|
9ae3a8 |
commit_start(bs, base_bs, top_bs, speed, on_error, block_job_cb, bs,
|
|
|
9ae3a8 |
- &local_err);
|
|
|
9ae3a8 |
+ has_backing_file ? backing_file : NULL, &local_err);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
if (local_err != NULL) {
|
|
|
9ae3a8 |
error_propagate(errp, local_err);
|
|
|
9ae3a8 |
diff --git a/include/block/block.h b/include/block/block.h
|
|
|
9ae3a8 |
index 972c0e7..03b7960 100644
|
|
|
9ae3a8 |
--- a/include/block/block.h
|
|
|
9ae3a8 |
+++ b/include/block/block.h
|
|
|
9ae3a8 |
@@ -256,7 +256,8 @@ int bdrv_change_backing_file(BlockDriverState *bs,
|
|
|
9ae3a8 |
const char *backing_file, const char *backing_fmt);
|
|
|
9ae3a8 |
void bdrv_register(BlockDriver *bdrv);
|
|
|
9ae3a8 |
int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
|
|
|
9ae3a8 |
- BlockDriverState *base);
|
|
|
9ae3a8 |
+ BlockDriverState *base,
|
|
|
9ae3a8 |
+ const char *backing_file_str);
|
|
|
9ae3a8 |
BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
|
|
|
9ae3a8 |
BlockDriverState *bs);
|
|
|
9ae3a8 |
BlockDriverState *bdrv_find_base(BlockDriverState *bs);
|
|
|
9ae3a8 |
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
|
|
9ae3a8 |
index 53fc98c..e6874b4 100644
|
|
|
9ae3a8 |
--- a/include/block/block_int.h
|
|
|
9ae3a8 |
+++ b/include/block/block_int.h
|
|
|
9ae3a8 |
@@ -389,13 +389,14 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
|
|
|
9ae3a8 |
* @on_error: The action to take upon error.
|
|
|
9ae3a8 |
* @cb: Completion function for the job.
|
|
|
9ae3a8 |
* @opaque: Opaque pointer value passed to @cb.
|
|
|
9ae3a8 |
+ * @backing_file_str: String to use as the backing file in @top's overlay
|
|
|
9ae3a8 |
* @errp: Error object.
|
|
|
9ae3a8 |
*
|
|
|
9ae3a8 |
*/
|
|
|
9ae3a8 |
void commit_start(BlockDriverState *bs, BlockDriverState *base,
|
|
|
9ae3a8 |
BlockDriverState *top, int64_t speed,
|
|
|
9ae3a8 |
BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
|
|
|
9ae3a8 |
- void *opaque, Error **errp);
|
|
|
9ae3a8 |
+ void *opaque, const char *backing_file_str, Error **errp);
|
|
|
9ae3a8 |
/**
|
|
|
9ae3a8 |
* commit_active_start:
|
|
|
9ae3a8 |
* @bs: Active block device to be committed.
|
|
|
9ae3a8 |
diff --git a/qapi-schema.json b/qapi-schema.json
|
|
|
9ae3a8 |
index 18ab949..ed79eb9 100644
|
|
|
9ae3a8 |
--- a/qapi-schema.json
|
|
|
9ae3a8 |
+++ b/qapi-schema.json
|
|
|
9ae3a8 |
@@ -1848,6 +1848,23 @@
|
|
|
9ae3a8 |
# which contains the topmost data to be committed down. If
|
|
|
9ae3a8 |
# not specified, this is the active layer.
|
|
|
9ae3a8 |
#
|
|
|
9ae3a8 |
+# @backing-file: #optional The backing file string to write into the overlay
|
|
|
9ae3a8 |
+# image of 'top'. If 'top' is the active layer,
|
|
|
9ae3a8 |
+# specifying a backing file string is an error. This
|
|
|
9ae3a8 |
+# 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
|
|
|
9ae3a8 |
+# there is no obvious choice. Care should be taken
|
|
|
9ae3a8 |
+# when specifying the string, to specify a valid
|
|
|
9ae3a8 |
+# filename or protocol.
|
|
|
9ae3a8 |
+# (Since 2.1)
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
# If top == base, that is an error.
|
|
|
9ae3a8 |
# If top == active, the job will not be completed by itself,
|
|
|
9ae3a8 |
# user needs to complete the job with the block-job-complete
|
|
|
9ae3a8 |
@@ -1860,7 +1877,6 @@
|
|
|
9ae3a8 |
# size of the smaller top, you can safely truncate it
|
|
|
9ae3a8 |
# yourself once the commit operation successfully completes.
|
|
|
9ae3a8 |
#
|
|
|
9ae3a8 |
-#
|
|
|
9ae3a8 |
# @speed: #optional the maximum speed, in bytes per second
|
|
|
9ae3a8 |
#
|
|
|
9ae3a8 |
# Returns: Nothing on success
|
|
|
9ae3a8 |
@@ -1875,7 +1891,7 @@
|
|
|
9ae3a8 |
##
|
|
|
9ae3a8 |
{ 'command': 'block-commit',
|
|
|
9ae3a8 |
'data': { 'device': 'str', '*base': 'str', '*top': 'str',
|
|
|
9ae3a8 |
- '*speed': 'int' } }
|
|
|
9ae3a8 |
+ '*backing-file': 'str', '*speed': 'int' } }
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
##
|
|
|
9ae3a8 |
# @drive-mirror
|
|
|
9ae3a8 |
diff --git a/qmp-commands.hx b/qmp-commands.hx
|
|
|
9ae3a8 |
index f67121a..5ece4f9 100644
|
|
|
9ae3a8 |
--- a/qmp-commands.hx
|
|
|
9ae3a8 |
+++ b/qmp-commands.hx
|
|
|
9ae3a8 |
@@ -1005,7 +1005,7 @@ EQMP
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
.name = "block-commit",
|
|
|
9ae3a8 |
- .args_type = "device:B,base:s?,top:s?,speed:o?",
|
|
|
9ae3a8 |
+ .args_type = "device:B,base:s?,top:s?,backing-file:s?,speed:o?",
|
|
|
9ae3a8 |
.mhandler.cmd_new = qmp_marshal_input_block_commit,
|
|
|
9ae3a8 |
},
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
@@ -1026,6 +1026,23 @@ Arguments:
|
|
|
9ae3a8 |
which contains the topmost data to be committed down. If
|
|
|
9ae3a8 |
not specified, this is the active layer. (json-string, optional)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+- backing-file: The backing file string to write into the overlay
|
|
|
9ae3a8 |
+ image of 'top'. If 'top' is the active layer,
|
|
|
9ae3a8 |
+ specifying a backing file string is an error. This
|
|
|
9ae3a8 |
+ 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
|
|
|
9ae3a8 |
+ there is no obvious choice. Care should be taken
|
|
|
9ae3a8 |
+ when specifying the string, to specify a valid
|
|
|
9ae3a8 |
+ filename or protocol.
|
|
|
9ae3a8 |
+ (json-string, optional) (Since 2.1)
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
If top == base, that is an error.
|
|
|
9ae3a8 |
If top == active, the job will not be completed by itself,
|
|
|
9ae3a8 |
user needs to complete the job with the block-job-complete
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|