qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 10/11] block: add backing-file option to block-st


From: Jeff Cody
Subject: [Qemu-devel] [PATCH v2 10/11] block: add backing-file option to block-stream
Date: Tue, 27 May 2014 10:28:40 -0400

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.

Signed-off-by: Jeff Cody <address@hidden>
---
 block/stream.c            | 13 ++++++++-----
 blockdev.c                | 12 +++++++++++-
 hmp-commands.hx           |  2 +-
 hmp.c                     |  2 ++
 include/block/block_int.h |  2 +-
 qapi-schema.json          | 18 +++++++++++++++++-
 qmp-commands.hx           |  2 +-
 7 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/block/stream.c b/block/stream.c
index 91d18a2..bf19a0e 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -32,7 +32,7 @@ typedef struct StreamBlockJob {
     RateLimit limit;
     BlockDriverState *base;
     BlockdevOnError on_error;
-    char backing_file_id[1024];
+    char *backing_file_str;
 } StreamBlockJob;
 
 static int coroutine_fn stream_populate(BlockDriverState *bs,
@@ -186,7 +186,7 @@ wait:
     if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) {
         const char *base_id = NULL, *base_fmt = NULL;
         if (base) {
-            base_id = s->backing_file_id;
+            base_id = s->backing_file_str;
             if (base->drv) {
                 base_fmt = base->drv->format_name;
             }
@@ -196,6 +196,7 @@ wait:
     }
 
     qemu_vfree(buf);
+    g_free(s->backing_file_str);
     block_job_completed(&s->common, ret);
 }
 
@@ -220,7 +221,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState 
*base,
                   const char *base_id, int64_t speed,
                   BlockdevOnError on_error,
                   BlockDriverCompletionFunc *cb,
-                  void *opaque, Error **errp)
+                  void *opaque, const char *backing_file_str, Error **errp)
 {
     StreamBlockJob *s;
 
@@ -237,8 +238,10 @@ void stream_start(BlockDriverState *bs, BlockDriverState 
*base,
     }
 
     s->base = base;
-    if (base_id) {
-        pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id);
+    if (backing_file_str) {
+        s->backing_file_str = g_strdup(backing_file_str);
+    } else {
+        s->backing_file_str = g_strdup(base_id);
     }
 
     s->on_error = on_error;
diff --git a/blockdev.c b/blockdev.c
index a4468b4..81d1383 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1873,6 +1873,7 @@ static void block_job_cb(void *opaque, int ret)
 void qmp_block_stream(bool has_device, const char *device,
                       bool has_base, const char *base,
                       bool has_base_node_name, const char *base_node_name,
+                      bool has_backing_file, const char *backing_file,
                       bool has_speed, int64_t speed,
                       bool has_on_error, BlockdevOnError on_error,
                       Error **errp)
@@ -1941,8 +1942,17 @@ void qmp_block_stream(bool has_device, const char 
*device,
         return;
     }
 
+    /* if we are streaming from the bottommost base image, then specifying
+     * a backing file does not make sense, and is an error */
+    if (base_bs == NULL && has_backing_file) {
+        error_setg(errp, "backing file specified, but streaming from "
+                         "bottommost base image");
+        return;
+    }
+
     stream_start(bs, base_bs, base_name, has_speed ? speed : 0,
-                 on_error, block_job_cb, bs, &local_err);
+                 on_error, block_job_cb, bs,
+                 has_backing_file ? backing_file : NULL, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 17eda87..5759252 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -76,7 +76,7 @@ ETEXI
 
     {
         .name       = "block_stream",
-        .args_type  = "device:B?,speed:o?,base:s?,base-node-name:s?",
+        .args_type  = 
"device:B?,speed:o?,base:s?,base-node-name:s?,backing-file:s?",
         .params     = "device [speed [base]]",
         .help       = "copy data from a backing file into a block device",
         .mhandler.cmd = hmp_block_stream,
diff --git a/hmp.c b/hmp.c
index 122aa29..69dd4f5 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1171,10 +1171,12 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
     const char *device         = qdict_get_str(qdict, "device");
     const char *base           = qdict_get_try_str(qdict, "base");
     const char *base_node_name = qdict_get_try_str(qdict, "base_node_name");
+    const char *backing_file   = qdict_get_try_str(qdict, "backing_file");
     int64_t speed              = qdict_get_try_int(qdict, "speed", 0);
 
     qmp_block_stream(device != NULL, device, base != NULL, base,
                      base_node_name != NULL, base_node_name,
+                     backing_file != NULL, backing_file,
                      qdict_haskey(qdict, "speed"), speed,
                      true, BLOCKDEV_ON_ERROR_REPORT, &error);
 
diff --git a/include/block/block_int.h b/include/block/block_int.h
index f5809ff..9f44c79 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -426,7 +426,7 @@ void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
 void stream_start(BlockDriverState *bs, BlockDriverState *base,
                   const char *base_id, int64_t speed, BlockdevOnError on_error,
                   BlockDriverCompletionFunc *cb,
-                  void *opaque, Error **errp);
+                  void *opaque, const char *backing_file, Error **errp);
 
 /**
  * commit_start:
diff --git a/qapi-schema.json b/qapi-schema.json
index 63e74c5..10be371 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2611,6 +2611,21 @@
 # @base-node-name: #optional the block driver state node name of the
 #                            common backing file.  (Since 2.1)
 #
+# @backing-file: #optional The backing file string to write into the active
+#                          layer. This filename is not validated.
+#
+#                          If a pathname string is such that it cannot be
+#                          resolved be QEMU, that means that subsequent QMP or
+#                          HMP commands must use node-names for the image in
+#                          question, as filename lookup methods will fail.
+#
+#                          If not specified, QEMU will automatically determine
+#                          the backing file string to use, or error out if 
there
+#                          is no obvious choice.  Care should be taken when
+#                          specifying the string, to specify a valid filename 
or
+#                          protocol.
+#                          (Since 2.1)
+#
 # @speed:  #optional the maximum speed, in bytes per second
 #
 # @on-error: #optional the action to take on an error (default report).
@@ -2624,7 +2639,8 @@
 ##
 { 'command': 'block-stream',
   'data': { '*device': 'str', '*base': 'str', '*base-node-name': 'str',
-            '*speed': 'int', '*on-error': 'BlockdevOnError' } }
+            '*backing-file': 'str', '*speed': 'int',
+            '*on-error': 'BlockdevOnError' } }
 
 ##
 # @block-job-set-speed:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 903c63a..837195d 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -979,7 +979,7 @@ EQMP
 
     {
         .name       = "block-stream",
-        .args_type  = 
"device:B?,base:s?,base-node-name:s?,speed:o?,on-error:s?",
+        .args_type  = 
"device:B?,base:s?,base-node-name:s?,speed:o?,backing-file:s?,on-error:s?",
         .mhandler.cmd_new = qmp_marshal_input_block_stream,
     },
 
-- 
1.8.3.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]