qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Jeff Cody <jcody@redhat.com>,
	Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PULL for-2.1 24/24] block: add backing-file option to block-stream
Date: Tue,  1 Jul 2014 10:48:57 +0200	[thread overview]
Message-ID: <1404204537-5082-25-git-send-email-stefanha@redhat.com> (raw)
In-Reply-To: <1404204537-5082-1-git-send-email-stefanha@redhat.com>

From: Jeff Cody <jcody@redhat.com>

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.

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/stream.c       | 11 +++++------
 blockdev.c           | 23 +++++++++++++++++++----
 hmp.c                |  2 +-
 qapi/block-core.json | 19 +++++++++++++++++--
 qmp-commands.hx      |  2 +-
 5 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/block/stream.c b/block/stream.c
index 0433409..34de8ba 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);
 }
 
@@ -217,7 +218,7 @@ static const BlockJobDriver stream_job_driver = {
 };
 
 void stream_start(BlockDriverState *bs, BlockDriverState *base,
-                  const char *base_id, int64_t speed,
+                  const char *backing_file_str, int64_t speed,
                   BlockdevOnError on_error,
                   BlockDriverCompletionFunc *cb,
                   void *opaque, Error **errp)
@@ -237,9 +238,7 @@ 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);
-    }
+    s->backing_file_str = g_strdup(backing_file_str);
 
     s->on_error = on_error;
     s->common.co = qemu_coroutine_create(stream_run);
diff --git a/blockdev.c b/blockdev.c
index 48315e8..48bd9a3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1871,14 +1871,17 @@ static void block_job_cb(void *opaque, int ret)
     bdrv_put_ref_bh_schedule(bs);
 }
 
-void qmp_block_stream(const char *device, bool has_base,
-                      const char *base, bool has_speed, int64_t speed,
+void qmp_block_stream(const char *device,
+                      bool has_base, const char *base,
+                      bool has_backing_file, const char *backing_file,
+                      bool has_speed, int64_t speed,
                       bool has_on_error, BlockdevOnError on_error,
                       Error **errp)
 {
     BlockDriverState *bs;
     BlockDriverState *base_bs = NULL;
     Error *local_err = NULL;
+    const char *base_name = NULL;
 
     if (!has_on_error) {
         on_error = BLOCKDEV_ON_ERROR_REPORT;
@@ -1894,15 +1897,27 @@ void qmp_block_stream(const char *device, bool has_base,
         return;
     }
 
-    if (base) {
+    if (has_base) {
         base_bs = bdrv_find_backing_image(bs, base);
         if (base_bs == NULL) {
             error_set(errp, QERR_BASE_NOT_FOUND, base);
             return;
         }
+        base_name = base;
     }
 
-    stream_start(bs, base_bs, base, has_speed ? speed : 0,
+    /* if we are streaming the entire chain, the result will have no backing
+     * file, and specifying one is therefore an error */
+    if (base_bs == NULL && has_backing_file) {
+        error_setg(errp, "backing file specified, but streaming the "
+                         "entire chain");
+        return;
+    }
+
+    /* backing_file string overrides base bs filename */
+    base_name = has_backing_file ? backing_file : base_name;
+
+    stream_start(bs, base_bs, base_name, has_speed ? speed : 0,
                  on_error, block_job_cb, bs, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
diff --git a/hmp.c b/hmp.c
index 6429e6b..4d1838e 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1176,7 +1176,7 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
     const char *base = qdict_get_try_str(qdict, "base");
     int64_t speed = qdict_get_try_int(qdict, "speed", 0);
 
-    qmp_block_stream(device, base != NULL, base,
+    qmp_block_stream(device, base != NULL, base, false, NULL,
                      qdict_haskey(qdict, "speed"), speed,
                      true, BLOCKDEV_ON_ERROR_REPORT, &error);
 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 5b4d75f..e378653 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -922,6 +922,21 @@
 #
 # @base:   #optional the common backing file name
 #
+# @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 by 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).
@@ -934,8 +949,8 @@
 # Since: 1.1
 ##
 { 'command': 'block-stream',
-  'data': { 'device': 'str', '*base': 'str', '*speed': 'int',
-            '*on-error': 'BlockdevOnError' } }
+  'data': { 'device': 'str', '*base': 'str', '*backing-file': 'str',
+            '*speed': 'int', '*on-error': 'BlockdevOnError' } }
 
 ##
 # @block-job-set-speed:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index a3f932c..4be4765 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -979,7 +979,7 @@ EQMP
 
     {
         .name       = "block-stream",
-        .args_type  = "device:B,base:s?,speed:o?,on-error:s?",
+        .args_type  = "device:B,base:s?,speed:o?,backing-file:s?,on-error:s?",
         .mhandler.cmd_new = qmp_marshal_input_block_stream,
     },
 
-- 
1.9.3

  parent reply	other threads:[~2014-07-01  8:50 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-01  8:48 [Qemu-devel] [PULL for-2.1 00/24] Block patches Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 01/24] qom: add object_property_add_alias() Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 02/24] virtio-blk: avoid qdev property definition duplication Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 03/24] dataplane: bail out on unsupported transport Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 04/24] virtio-blk: move x-data-plane qdev property to virtio-blk.h Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 05/24] qdev: add qdev_alias_all_properties() Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 06/24] virtio-blk: use aliases instead of duplicate qdev properties Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 07/24] virtio-blk: drop virtio_blk_set_conf() Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 08/24] virtio: fix virtio-blk child refcount in transports Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 09/24] virtio-blk: move qdev properties into virtio-blk.c Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 10/24] virtio-blk: replace x-iothread with iothread link property Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 11/24] qdev: drop iothread property type Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 12/24] virtio-blk: remove need for explicit x-data-plane=on option Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 13/24] qemu-img create: add 'nocow' option Stefan Hajnoczi
2014-07-02  3:10   ` Eric Blake
2014-07-02  4:34     ` Chun Yan Liu
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 14/24] iotests: Simplify qemu-iotests-quick.sh Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 15/24] iotests: Add qemu tests to quick group Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 16/24] iotests: Add more " Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 17/24] block: make 'top' argument to block-commit optional Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 18/24] block: simplify bdrv_find_base() and bdrv_find_overlay() Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 19/24] block/cow: Avoid use of uninitialized cow_bs in error path Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 20/24] qapi: Change back sector-count to sectors-count in quorum QAPI events Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 21/24] block: add QAPI command to allow live backing file change Stefan Hajnoczi
2014-07-01 22:09   ` Eric Blake
2014-07-02 13:53     ` Kevin Wolf
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 22/24] block: add helper function to determine if a BDS is in a chain Stefan Hajnoczi
2014-07-01  8:48 ` [Qemu-devel] [PULL for-2.1 23/24] block: extend block-commit to accept a string for the backing file Stefan Hajnoczi
2014-07-01  8:48 ` Stefan Hajnoczi [this message]
2014-07-01 20:50   ` [Qemu-devel] [PULL for-2.1 24/24] block: add backing-file option to block-stream Eric Blake
2014-07-01 22:06     ` Eric Blake
2014-07-01 13:21 ` [Qemu-devel] [PULL for-2.1 00/24] Block patches Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1404204537-5082-25-git-send-email-stefanha@redhat.com \
    --to=stefanha@redhat.com \
    --cc=jcody@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).