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