Patchwork [02/15] block: Add driver-specific options for backing files

login
register
mail settings
Submitter Kevin Wolf
Date April 12, 2013, 8:47 p.m.
Message ID <1365799688-19918-3-git-send-email-kwolf@redhat.com>
Download mbox | patch
Permalink /patch/236195/
State New
Headers show

Comments

Kevin Wolf - April 12, 2013, 8:47 p.m.
Options starting in "backing." are passed to the backing file now. If
you don't need to specify the filename for the backing file, you can add
it on the command line instead of in the image file:

$ qemu-nbd -t /tmp/test.img
$ qemu-img create -f qcow2 empty.qcow2 1G
$ qemu-system-x86_64 -drive file=empty.qcow2,backing.file.driver=nbd,\
    backing.file.host=localhost

Note that this doesn't override the backing filename from the image. If
the image has one, this will fail because NBD doesn't want the options
and a filename at the same time.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c               | 27 +++++++++++++++++++++++----
 block/mirror.c        |  2 +-
 include/block/block.h |  2 +-
 3 files changed, 25 insertions(+), 6 deletions(-)
Eric Blake - April 15, 2013, 5:38 p.m.
On 04/12/2013 02:47 PM, Kevin Wolf wrote:
> Options starting in "backing." are passed to the backing file now. If
> you don't need to specify the filename for the backing file, you can add
> it on the command line instead of in the image file:
> 
> $ qemu-nbd -t /tmp/test.img
> $ qemu-img create -f qcow2 empty.qcow2 1G
> $ qemu-system-x86_64 -drive file=empty.qcow2,backing.file.driver=nbd,\
>     backing.file.host=localhost

So effectively empty.qcow2 is booted as though it had an explicit
nbd://localhost in its backing metadata?  Looks interesting!

> 
> Note that this doesn't override the backing filename from the image. If
> the image has one, this will fail because NBD doesn't want the options
> and a filename at the same time.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  block.c               | 27 +++++++++++++++++++++++----
>  block/mirror.c        |  2 +-
>  include/block/block.h |  2 +-
>  3 files changed, 25 insertions(+), 6 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

Patch

diff --git a/block.c b/block.c
index f23bdcc..fc19df1 100644
--- a/block.c
+++ b/block.c
@@ -845,18 +845,33 @@  fail:
     return ret;
 }
 
-int bdrv_open_backing_file(BlockDriverState *bs)
+/*
+ * Opens the backing file for a BlockDriverState if not yet open
+ *
+ * options is a QDict of options to pass to the block drivers, or NULL for an
+ * empty set of options. The reference to the QDict is transferred to this
+ * function (even on failure), so if the caller intends to reuse the dictionary,
+ * it needs to use QINCREF() before calling bdrv_file_open.
+ */
+int bdrv_open_backing_file(BlockDriverState *bs, QDict *options)
 {
     char backing_filename[PATH_MAX];
     int back_flags, ret;
     BlockDriver *back_drv = NULL;
 
     if (bs->backing_hd != NULL) {
+        QDECREF(options);
         return 0;
     }
 
+    /* NULL means an empty set of options */
+    if (options == NULL) {
+        options = qdict_new();
+    }
+
     bs->open_flags &= ~BDRV_O_NO_BACKING;
-    if (bs->backing_file[0] == '\0') {
+    if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
+        QDECREF(options);
         return 0;
     }
 
@@ -871,7 +886,8 @@  int bdrv_open_backing_file(BlockDriverState *bs)
     /* backing files always opened read-only */
     back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT);
 
-    ret = bdrv_open(bs->backing_hd, backing_filename, NULL,
+    ret = bdrv_open(bs->backing_hd,
+                    *backing_filename ? backing_filename : NULL, options,
                     back_flags, back_drv);
     if (ret < 0) {
         bdrv_delete(bs->backing_hd);
@@ -1027,7 +1043,10 @@  int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
 
     /* If there is a backing file, use it */
     if ((flags & BDRV_O_NO_BACKING) == 0) {
-        ret = bdrv_open_backing_file(bs);
+        QDict *backing_options;
+
+        extract_subqdict(options, &backing_options, "backing.");
+        ret = bdrv_open_backing_file(bs, backing_options);
         if (ret < 0) {
             goto close_and_fail;
         }
diff --git a/block/mirror.c b/block/mirror.c
index a62ad86..8b07dec 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -507,7 +507,7 @@  static void mirror_complete(BlockJob *job, Error **errp)
     MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
     int ret;
 
-    ret = bdrv_open_backing_file(s->target);
+    ret = bdrv_open_backing_file(s->target, NULL);
     if (ret < 0) {
         char backing_filename[PATH_MAX];
         bdrv_get_full_backing_filename(s->target, backing_filename,
diff --git a/include/block/block.h b/include/block/block.h
index 9dc6aad..a512f1b 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -137,7 +137,7 @@  int bdrv_parse_cache_flags(const char *mode, int *flags);
 int bdrv_parse_discard_flags(const char *mode, int *flags);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename,
                    QDict *options, int flags);
-int bdrv_open_backing_file(BlockDriverState *bs);
+int bdrv_open_backing_file(BlockDriverState *bs, QDict *options);
 int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
               int flags, BlockDriver *drv);
 BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,