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