qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [v19 05/25] change block layer to support both QemuOpts and


From: Chunyan Liu
Subject: [Qemu-devel] [v19 05/25] change block layer to support both QemuOpts and QEMUOptionParameter
Date: Mon, 20 Jan 2014 22:19:48 +0800

Change block layer to support both QemuOpts and QEMUOptionParameter.
After this patch, it will change backend drivers one by one. At the end,
QEMUOptionParameter will be removed and only QemuOpts is kept.

Signed-off-by: Dong Xu Wang <address@hidden>
Signed-off-by: Chunyan Liu <address@hidden>
---
 block.c                   |  339 +++++++++++++++++++++++++++++++--------------
 block/cow.c               |    2 +-
 block/qcow.c              |    2 +-
 block/qcow2.c             |    2 +-
 block/qed.c               |    2 +-
 block/raw_bsd.c           |    2 +-
 block/vhdx.c              |    2 +-
 block/vmdk.c              |    4 +-
 block/vvfat.c             |    2 +-
 include/block/block.h     |    4 +-
 include/block/block_int.h |    4 +-
 qemu-img.c                |  172 ++++++++++++++++-------
 12 files changed, 372 insertions(+), 165 deletions(-)

diff --git a/block.c b/block.c
index 64e7d22..0dc0b09 100644
--- a/block.c
+++ b/block.c
@@ -395,6 +395,7 @@ typedef struct CreateCo {
     BlockDriver *drv;
     char *filename;
     QEMUOptionParameter *options;
+    QemuOpts *opts;
     int ret;
     Error *err;
 } CreateCo;
@@ -407,7 +408,10 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
     CreateCo *cco = opaque;
     assert(cco->drv);
 
-    ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err);
+    if (cco->drv->bdrv_create2)
+        ret = cco->drv->bdrv_create2(cco->filename, cco->opts, &local_err);
+    else
+        ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err);
     if (error_is_set(&local_err)) {
         error_propagate(&cco->err, local_err);
     }
@@ -415,7 +419,7 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
 }
 
 int bdrv_create(BlockDriver *drv, const char* filename,
-    QEMUOptionParameter *options, Error **errp)
+    QEMUOptionParameter *options, QemuOpts *opts, Error **errp)
 {
     int ret;
 
@@ -424,11 +428,12 @@ int bdrv_create(BlockDriver *drv, const char* filename,
         .drv = drv,
         .filename = g_strdup(filename),
         .options = options,
+        .opts = opts,
         .ret = NOT_DONE,
         .err = NULL,
     };
 
-    if (!drv->bdrv_create) {
+    if (!drv->bdrv_create && !drv->bdrv_create2) {
         error_setg(errp, "Driver '%s' does not support image creation", 
drv->format_name);
         ret = -ENOTSUP;
         goto out;
@@ -460,7 +465,7 @@ out:
 }
 
 int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
-                     Error **errp)
+                     QemuOpts *opts, Error **errp)
 {
     BlockDriver *drv;
     Error *local_err = NULL;
@@ -472,7 +477,7 @@ int bdrv_create_file(const char* filename, 
QEMUOptionParameter *options,
         return -ENOENT;
     }
 
-    ret = bdrv_create(drv, filename, options, &local_err);
+    ret = bdrv_create(drv, filename, options, opts, &local_err);
     if (error_is_set(&local_err)) {
         error_propagate(errp, local_err);
     }
@@ -1053,7 +1058,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, 
QDict *options,
         BlockDriverState *bs1;
         int64_t total_size;
         BlockDriver *bdrv_qcow2;
-        QEMUOptionParameter *create_options;
+        QEMUOptionParameter *create_options = NULL;
+        QemuOpts *opts = NULL; 
         QDict *snapshot_options;
 
         /* if snapshot, we create a temporary backing file and open it
@@ -1080,13 +1086,18 @@ int bdrv_open(BlockDriverState *bs, const char 
*filename, QDict *options,
         }
 
         bdrv_qcow2 = bdrv_find_format("qcow2");
-        create_options = parse_option_parameters("", 
bdrv_qcow2->create_options,
-                                                 NULL);
-
-        set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
+        if (bdrv_qcow2->bdrv_create2) {
+            opts = qemu_opts_create(bdrv_qcow2->create_opts, NULL, 0, 
&error_abort);
+            qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size);
+        } else {
+            create_options = 
+                parse_option_parameters("", bdrv_qcow2->create_options, NULL);
+            set_option_parameter_int(create_options, BLOCK_OPT_SIZE, 
total_size);
+        }
 
-        ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, 
&local_err);
+        ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, opts, 
&local_err);
         free_option_parameters(create_options);
+        qemu_opts_del(opts);
         if (ret < 0) {
             error_setg_errno(errp, -ret, "Could not create temporary overlay "
                              "'%s': %s", tmp_filename,
@@ -4712,7 +4723,8 @@ void bdrv_img_create(const char *filename, const char 
*fmt,
                      Error **errp, bool quiet)
 {
     QEMUOptionParameter *param = NULL, *create_options = NULL;
-    QEMUOptionParameter *backing_fmt, *backing_file, *size;
+    QemuOptsList *create_opts = NULL;
+    QemuOpts *opts = NULL;
     BlockDriver *drv, *proto_drv;
     BlockDriver *backing_drv = NULL;
     Error *local_err = NULL;
@@ -4731,125 +4743,246 @@ void bdrv_img_create(const char *filename, const char 
*fmt,
         return;
     }
 
-    create_options = append_option_parameters(create_options,
-                                              drv->create_options);
-    create_options = append_option_parameters(create_options,
-                                              proto_drv->create_options);
+    if (drv->bdrv_create2) {
+        const char *backing_fmt, *backing_file;
+        int64_t size;
 
-    /* Create parameter list with default values */
-    param = parse_option_parameters("", create_options, param);
+        create_opts = qemu_opts_append(create_opts, drv->create_opts);
+        create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
+        /* Create parameter list with default values */
+        opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
 
-    set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
+        qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size);
 
-    /* Parse -o options */
-    if (options) {
-        param = parse_option_parameters(options, create_options, param);
-        if (param == NULL) {
-            error_setg(errp, "Invalid options for file format '%s'.", fmt);
-            goto out;
+        /* Parse -o options */
+        if (options) {
+            if (qemu_opts_do_parse(opts, options, NULL) != 0) {
+                error_setg(errp, "Invalid options for file format '%s'.", fmt);
+                goto out;
+            }
         }
-    }
 
-    if (base_filename) {
-        if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE,
-                                 base_filename)) {
-            error_setg(errp, "Backing file not supported for file format '%s'",
-                       fmt);
-            goto out;
+        if (base_filename) {
+            if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
+                error_setg(errp, "Backing file not supported for file format 
'%s'",
+                           fmt);
+                goto out;
+            }
         }
-    }
 
-    if (base_fmt) {
-        if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
-            error_setg(errp, "Backing file format not supported for file "
-                             "format '%s'", fmt);
-            goto out;
+        if (base_fmt) {
+            if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+                error_setg(errp, "Backing file format not supported for file "
+                                 "format '%s'", fmt);
+                goto out;
+            }
         }
-    }
 
-    backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
-    if (backing_file && backing_file->value.s) {
-        if (!strcmp(filename, backing_file->value.s)) {
-            error_setg(errp, "Error: Trying to create an image with the "
-                             "same filename as the backing file");
-            goto out;
+        backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+        if (backing_file) {
+            if (!strcmp(filename, backing_file)) {
+                error_setg(errp, "Error: Trying to create an image with the "
+                                 "same filename as the backing file");
+                goto out;
+            }
         }
-    }
 
-    backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
-    if (backing_fmt && backing_fmt->value.s) {
-        backing_drv = bdrv_find_format(backing_fmt->value.s);
-        if (!backing_drv) {
-            error_setg(errp, "Unknown backing file format '%s'",
-                       backing_fmt->value.s);
-            goto out;
+        backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
+        if (backing_fmt) {
+            backing_drv = bdrv_find_format(backing_fmt);
+            if (!backing_drv) {
+                error_setg(errp, "Unknown backing file format '%s'",
+                           backing_fmt);
+                goto out;
+            }
+        }
+
+        // The size for the image must always be specified, with one exception:
+        // If we are using a backing file, we can obtain the size from there
+        size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
+        if (size == -1) {
+            if (backing_file) {
+                BlockDriverState *bs;
+                uint64_t size;
+                char buf[32];
+                int back_flags;
+
+                /* backing files always opened read-only */
+                back_flags =
+                     flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | 
BDRV_O_NO_BACKING);
+
+                bs = bdrv_new("");
+
+                ret = bdrv_open(bs, backing_file, NULL, back_flags,
+                                backing_drv, &local_err);
+                if (ret < 0) {
+                    error_setg_errno(errp, -ret, "Could not open '%s': %s",
+                                     backing_file,
+                                     error_get_pretty(local_err));
+                    error_free(local_err);
+                    local_err = NULL;
+                    bdrv_unref(bs);
+                    goto out;
+                }
+                bdrv_get_geometry(bs, &size);
+                size *= 512;
+
+                snprintf(buf, sizeof(buf), "%" PRId64, size);
+                qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size);
+
+                bdrv_unref(bs);
+            } else {
+                error_setg(errp, "Image creation needs a size parameter");
+                goto out;
+            }
+        }
+
+        if (!quiet) {
+            printf("Formatting '%s', fmt=%s ", filename, fmt);
+            qemu_opts_print(opts);
+            puts("");
+        }
+
+        ret = bdrv_create(drv, filename, NULL, opts, &local_err);
+        if (ret == -EFBIG) {
+            /* This is generally a better message than whatever the driver 
would
+             * deliver (especially because of the cluster_size_hint), since 
that
+             * is most probably not much different from "image too large". */
+            const char *cluster_size_hint = "";
+            if (qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE, 0)) {
+                cluster_size_hint = " (try using a larger cluster size)";
+            }
+            error_setg(errp, "The image size is too large for file format '%s'"
+                       "%s", fmt, cluster_size_hint);
+            error_free(local_err);
+            local_err = NULL;
         }
-    }
 
-    // The size for the image must always be specified, with one exception:
-    // If we are using a backing file, we can obtain the size from there
-    size = get_option_parameter(param, BLOCK_OPT_SIZE);
-    if (size && size->value.n == -1) {
+    } else {
+        QEMUOptionParameter *backing_fmt, *backing_file, *size;
+
+        create_options = append_option_parameters(create_options,
+                                                  drv->create_options);
+        create_options = append_option_parameters(create_options,
+                                                  proto_drv->create_options);
+
+        /* Create parameter list with default values */
+        param = parse_option_parameters("", create_options, param);
+
+        set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
+
+        /* Parse -o options */
+        if (options) {
+            param = parse_option_parameters(options, create_options, param);
+            if (param == NULL) {
+                error_setg(errp, "Invalid options for file format '%s'.", fmt);
+                goto out;
+            }
+        }
+
+        if (base_filename) {
+            if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE,
+                                     base_filename)) {
+                error_setg(errp, "Backing file not supported for file format 
'%s'",
+                           fmt);
+                goto out;
+            }
+        }
+
+        if (base_fmt) {
+            if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+                error_setg(errp, "Backing file format not supported for file "
+                                 "format '%s'", fmt);
+                goto out;
+            }
+        }
+
+        backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
         if (backing_file && backing_file->value.s) {
-            BlockDriverState *bs;
-            uint64_t size;
-            char buf[32];
-            int back_flags;
+            if (!strcmp(filename, backing_file->value.s)) {
+                error_setg(errp, "Error: Trying to create an image with the "
+                                 "same filename as the backing file");
+                goto out;
+            }
+        }
 
-            /* backing files always opened read-only */
-            back_flags =
-                flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+        backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
+        if (backing_fmt && backing_fmt->value.s) {
+            backing_drv = bdrv_find_format(backing_fmt->value.s);
+            if (!backing_drv) {
+                error_setg(errp, "Unknown backing file format '%s'",
+                           backing_fmt->value.s);
+                goto out;
+            }
+        }
 
-            bs = bdrv_new("");
+        // The size for the image must always be specified, with one exception:
+        // If we are using a backing file, we can obtain the size from there
+        size = get_option_parameter(param, BLOCK_OPT_SIZE);
+        if (size && size->value.n == -1) {
+            if (backing_file && backing_file->value.s) {
+                BlockDriverState *bs;
+                uint64_t size;
+                char buf[32];
+                int back_flags;
+
+                /* backing files always opened read-only */
+                back_flags =
+                    flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | 
BDRV_O_NO_BACKING);
+
+                bs = bdrv_new("");
+
+                ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags,
+                                backing_drv, &local_err);
+                if (ret < 0) {
+                    error_setg_errno(errp, -ret, "Could not open '%s': %s",
+                                     backing_file->value.s,
+                                     error_get_pretty(local_err));
+                    error_free(local_err);
+                    local_err = NULL;
+                    bdrv_unref(bs);
+                    goto out;
+                }
+                bdrv_get_geometry(bs, &size);
+                size *= 512;
+
+                snprintf(buf, sizeof(buf), "%" PRId64, size);
+                set_option_parameter(param, BLOCK_OPT_SIZE, buf);
 
-            ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags,
-                            backing_drv, &local_err);
-            if (ret < 0) {
-                error_setg_errno(errp, -ret, "Could not open '%s': %s",
-                                 backing_file->value.s,
-                                 error_get_pretty(local_err));
-                error_free(local_err);
-                local_err = NULL;
                 bdrv_unref(bs);
+            } else {
+                error_setg(errp, "Image creation needs a size parameter");
                 goto out;
             }
-            bdrv_get_geometry(bs, &size);
-            size *= 512;
-
-            snprintf(buf, sizeof(buf), "%" PRId64, size);
-            set_option_parameter(param, BLOCK_OPT_SIZE, buf);
+        }
 
-            bdrv_unref(bs);
-        } else {
-            error_setg(errp, "Image creation needs a size parameter");
-            goto out;
+        if (!quiet) {
+            printf("Formatting '%s', fmt=%s ", filename, fmt);
+            print_option_parameters(param);
+            puts("");
         }
-    }
 
-    if (!quiet) {
-        printf("Formatting '%s', fmt=%s ", filename, fmt);
-        print_option_parameters(param);
-        puts("");
-    }
-    ret = bdrv_create(drv, filename, param, &local_err);
-    if (ret == -EFBIG) {
-        /* This is generally a better message than whatever the driver would
-         * deliver (especially because of the cluster_size_hint), since that
-         * is most probably not much different from "image too large". */
-        const char *cluster_size_hint = "";
-        if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) {
-            cluster_size_hint = " (try using a larger cluster size)";
+        ret = bdrv_create(drv, filename, param, NULL, &local_err);
+        if (ret == -EFBIG) {
+            /* This is generally a better message than whatever the driver 
would
+             * deliver (especially because of the cluster_size_hint), since 
that
+             * is most probably not much different from "image too large". */
+            const char *cluster_size_hint = "";
+            if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) {
+                cluster_size_hint = " (try using a larger cluster size)";
+            }
+            error_setg(errp, "The image size is too large for file format '%s'"
+                       "%s", fmt, cluster_size_hint);
+            error_free(local_err);
+            local_err = NULL;
         }
-        error_setg(errp, "The image size is too large for file format '%s'"
-                   "%s", fmt, cluster_size_hint);
-        error_free(local_err);
-        local_err = NULL;
-    }
+   }
 
 out:
     free_option_parameters(create_options);
     free_option_parameters(param);
-
+    qemu_opts_del(opts);
+    qemu_opts_free(create_opts);
     if (error_is_set(&local_err)) {
         error_propagate(errp, local_err);
     }
diff --git a/block/cow.c b/block/cow.c
index dc15e46..6318228 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -344,7 +344,7 @@ static int cow_create(const char *filename, 
QEMUOptionParameter *options,
         options++;
     }
 
-    ret = bdrv_create_file(filename, options, &local_err);
+    ret = bdrv_create_file(filename, options, NULL, &local_err);
     if (ret < 0) {
         qerror_report_err(local_err);
         error_free(local_err);
diff --git a/block/qcow.c b/block/qcow.c
index c470e05..be2a72e 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -684,7 +684,7 @@ static int qcow_create(const char *filename, 
QEMUOptionParameter *options,
         options++;
     }
 
-    ret = bdrv_create_file(filename, options, &local_err);
+    ret = bdrv_create_file(filename, options, NULL, &local_err);
     if (ret < 0) {
         qerror_report_err(local_err);
         error_free(local_err);
diff --git a/block/qcow2.c b/block/qcow2.c
index 8ec9db1..e8b96cd 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1477,7 +1477,7 @@ static int qcow2_create2(const char *filename, int64_t 
total_size,
     Error *local_err = NULL;
     int ret;
 
-    ret = bdrv_create_file(filename, options, &local_err);
+    ret = bdrv_create_file(filename, options, NULL, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         return ret;
diff --git a/block/qed.c b/block/qed.c
index 450a1fa..4221ee2 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -556,7 +556,7 @@ static int qed_create(const char *filename, uint32_t 
cluster_size,
     int ret = 0;
     BlockDriverState *bs = NULL;
 
-    ret = bdrv_create_file(filename, NULL, &local_err);
+    ret = bdrv_create_file(filename, NULL, NULL, &local_err);
     if (ret < 0) {
         qerror_report_err(local_err);
         error_free(local_err);
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index 978ae7a..297e03f 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -139,7 +139,7 @@ static int raw_create(const char *filename, 
QEMUOptionParameter *options,
     Error *local_err = NULL;
     int ret;
 
-    ret = bdrv_create_file(filename, options, &local_err);
+    ret = bdrv_create_file(filename, options, NULL, &local_err);
     if (error_is_set(&local_err)) {
         error_propagate(errp, local_err);
     }
diff --git a/block/vhdx.c b/block/vhdx.c
index 1995778..c78675e 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1791,7 +1791,7 @@ static int vhdx_create(const char *filename, 
QEMUOptionParameter *options,
     block_size = block_size > VHDX_BLOCK_SIZE_MAX ? VHDX_BLOCK_SIZE_MAX :
                                                     block_size;
 
-    ret = bdrv_create_file(filename, options, &local_err);
+    ret = bdrv_create_file(filename, options, NULL, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto exit;
diff --git a/block/vmdk.c b/block/vmdk.c
index c6b60b4..974eaff 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1463,7 +1463,7 @@ static int vmdk_create_extent(const char *filename, 
int64_t filesize,
     uint32_t *gd_buf = NULL;
     int gd_buf_size;
 
-    ret = bdrv_create_file(filename, NULL, &local_err);
+    ret = bdrv_create_file(filename, NULL, NULL, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto exit;
@@ -1801,7 +1801,7 @@ static int vmdk_create(const char *filename, 
QEMUOptionParameter *options,
     if (!split && !flat) {
         desc_offset = 0x200;
     } else {
-        ret = bdrv_create_file(filename, options, &local_err);
+        ret = bdrv_create_file(filename, options, NULL, &local_err);
         if (ret < 0) {
             error_setg_errno(errp, -ret, "Could not create image file");
             goto exit;
diff --git a/block/vvfat.c b/block/vvfat.c
index 664941c..c59cbdb 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2929,7 +2929,7 @@ static int enable_write_target(BDRVVVFATState *s)
     set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
     set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
 
-    ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, &local_err);
+    ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, NULL, &local_err);
     if (ret < 0) {
         qerror_report_err(local_err);
         error_free(local_err);
diff --git a/include/block/block.h b/include/block/block.h
index 36efaea..687d423 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -174,9 +174,9 @@ BlockDriver *bdrv_find_format(const char *format_name);
 BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
                                           bool readonly);
 int bdrv_create(BlockDriver *drv, const char* filename,
-    QEMUOptionParameter *options, Error **errp);
+    QEMUOptionParameter *options, QemuOpts *opts, Error **errp);
 int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
-                     Error **errp);
+                     QemuOpts *opts, Error **errp);
 BlockDriverState *bdrv_new(const char *device_name);
 void bdrv_make_anon(BlockDriverState *bs);
 void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 2772f2f..f0043f8 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -105,6 +105,8 @@ struct BlockDriver {
     void (*bdrv_rebind)(BlockDriverState *bs);
     int (*bdrv_create)(const char *filename, QEMUOptionParameter *options,
                        Error **errp);
+    int (*bdrv_create2)(const char *filename, QemuOpts *opts,
+                       Error **errp);
     int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
     int (*bdrv_make_empty)(BlockDriverState *bs);
     /* aio */
@@ -204,7 +206,7 @@ struct BlockDriver {
 
     /* List of options for creating images, terminated by name == NULL */
     QEMUOptionParameter *create_options;
-
+    QemuOptsList *create_opts;
 
     /*
      * Returns 0 for completed check, -errno for internal errors.
diff --git a/qemu-img.c b/qemu-img.c
index c989850..05052d9 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -242,6 +242,7 @@ static int print_block_option_help(const char *filename, 
const char *fmt)
 {
     BlockDriver *drv, *proto_drv;
     QEMUOptionParameter *create_options = NULL;
+    QemuOptsList *create_opts = NULL;
 
     /* Find driver and parse its options */
     drv = bdrv_find_format(fmt);
@@ -256,12 +257,19 @@ static int print_block_option_help(const char *filename, 
const char *fmt)
         return 1;
     }
 
-    create_options = append_option_parameters(create_options,
-                                              drv->create_options);
-    create_options = append_option_parameters(create_options,
-                                              proto_drv->create_options);
-    print_option_help(create_options);
+    if (drv->bdrv_create2) {
+        create_opts = qemu_opts_append(create_opts, drv->create_opts);
+        create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
+        qemu_opts_print_help(create_opts);
+    } else {
+        create_options = append_option_parameters(create_options,
+                                                  drv->create_options);
+        create_options = append_option_parameters(create_options,
+                                                  proto_drv->create_options);
+        print_option_help(create_options);
+    }
     free_option_parameters(create_options);
+    qemu_opts_free(create_opts);
     return 0;
 }
 
@@ -317,18 +325,21 @@ fail:
 }
 
 static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
+                                 QemuOpts *opts,
                                  const char *base_filename,
                                  const char *base_fmt)
 {
     if (base_filename) {
-        if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) 
{
+        if ((opts && qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, 
base_filename)) ||
+            (list && set_option_parameter(list, BLOCK_OPT_BACKING_FILE, 
base_filename))) {
             error_report("Backing file not supported for file format '%s'",
                          fmt);
             return -1;
         }
     }
     if (base_fmt) {
-        if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+        if ((opts && qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) ||
+            (list && set_option_parameter(list, BLOCK_OPT_BACKING_FMT, 
base_fmt))) {
             error_report("Backing file format not supported for file "
                          "format '%s'", fmt);
             return -1;
@@ -1142,7 +1153,8 @@ static int img_convert(int argc, char **argv)
     const uint8_t *buf1;
     BlockDriverInfo bdi;
     QEMUOptionParameter *param = NULL, *create_options = NULL;
-    QEMUOptionParameter *out_baseimg_param;
+    QemuOpts *opts = NULL;
+    QemuOptsList *create_opts = NULL;
     char *options = NULL;
     const char *snapshot_name = NULL;
     int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
@@ -1312,67 +1324,125 @@ static int img_convert(int argc, char **argv)
         goto out;
     }
 
-    create_options = append_option_parameters(create_options,
-                                              drv->create_options);
-    create_options = append_option_parameters(create_options,
-                                              proto_drv->create_options);
+    if (drv->bdrv_create2) {
+        const char *out_baseimg_param;
 
-    if (options) {
-        param = parse_option_parameters(options, create_options, param);
-        if (param == NULL) {
+        create_opts = qemu_opts_append(create_opts, drv->create_opts);
+        create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
+        opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+        if (options && qemu_opts_do_parse(opts, options, NULL)) {
             error_report("Invalid options for file format '%s'.", out_fmt);
             ret = -1;
             goto out;
         }
-    } else {
-        param = parse_option_parameters("", create_options, param);
-    }
 
-    set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
-    ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
-    if (ret < 0) {
-        goto out;
-    }
+        qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512);
+        ret = add_old_style_options(out_fmt, NULL, opts, out_baseimg, NULL);
+        if (ret < 0) {
+            goto out;
+        }
 
-    /* Get backing file name if -o backing_file was used */
-    out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
-    if (out_baseimg_param) {
-        out_baseimg = out_baseimg_param->value.s;
-    }
+        /* Get backing file name if -o backing_file was used */
+        out_baseimg_param = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+        if (out_baseimg_param) {
+            out_baseimg = out_baseimg_param;
+        }
 
-    /* Check if compression is supported */
-    if (compress) {
-        QEMUOptionParameter *encryption =
-            get_option_parameter(param, BLOCK_OPT_ENCRYPT);
-        QEMUOptionParameter *preallocation =
-            get_option_parameter(param, BLOCK_OPT_PREALLOC);
+        /* Check if compression is supported */
+        if (compress) {
+            bool encryption =
+                qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
+            const char *preallocation =
+                qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
 
-        if (!drv->bdrv_write_compressed) {
-            error_report("Compression not supported for this file format");
-            ret = -1;
-            goto out;
+            if (!drv->bdrv_write_compressed) {
+                error_report("Compression not supported for this file format");
+                ret = -1;
+                goto out;
+            }
+
+            if (encryption) {
+                error_report("Compression and encryption not supported at "
+                             "the same time");
+                ret = -1;
+                goto out;
+            }
+
+            if (preallocation
+                && strcmp(preallocation, "off"))
+            {
+                error_report("Compression and preallocation not supported at "
+                             "the same time");
+                ret = -1;
+                goto out;
+            }
         }
 
-        if (encryption && encryption->value.n) {
-            error_report("Compression and encryption not supported at "
-                         "the same time");
-            ret = -1;
-            goto out;
+    } else {
+        QEMUOptionParameter *out_baseimg_param;
+
+        create_options = append_option_parameters(create_options,
+                                                  drv->create_options);
+        create_options = append_option_parameters(create_options,
+                                                  proto_drv->create_options);
+
+        if (options) {
+            param = parse_option_parameters(options, create_options, param);
+            if (param == NULL) {
+                error_report("Invalid options for file format '%s'.", out_fmt);
+                ret = -1;
+                goto out;
+            }
+        } else {
+            param = parse_option_parameters("", create_options, param);
         }
 
-        if (preallocation && preallocation->value.s
-            && strcmp(preallocation->value.s, "off"))
-        {
-            error_report("Compression and preallocation not supported at "
-                         "the same time");
-            ret = -1;
+        set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
+        ret = add_old_style_options(out_fmt, param, NULL, out_baseimg, NULL);
+        if (ret < 0) {
             goto out;
         }
+
+        /* Get backing file name if -o backing_file was used */
+        out_baseimg_param = get_option_parameter(param, 
BLOCK_OPT_BACKING_FILE);
+        if (out_baseimg_param) {
+            out_baseimg = out_baseimg_param->value.s;
+        }
+
+        /* Check if compression is supported */
+        if (compress) {
+            QEMUOptionParameter *encryption =
+                get_option_parameter(param, BLOCK_OPT_ENCRYPT);
+            QEMUOptionParameter *preallocation =
+                get_option_parameter(param, BLOCK_OPT_PREALLOC);
+
+            if (!drv->bdrv_write_compressed) {
+                error_report("Compression not supported for this file format");
+                ret = -1;
+                goto out;
+            }
+
+            if (encryption && encryption->value.n) {
+                error_report("Compression and encryption not supported at "
+                             "the same time");
+                ret = -1;
+                goto out;
+            }
+
+            if (preallocation && preallocation->value.s
+                && strcmp(preallocation->value.s, "off"))
+            {
+                error_report("Compression and preallocation not supported at "
+                             "the same time");
+                ret = -1;
+                goto out;
+            }
+        }
     }
 
     if (!skip_create) {
         /* Create the new image */
-        ret = bdrv_create(drv, out_filename, param, &local_err);
+        ret = bdrv_create(drv, out_filename, param, opts, &local_err);
         if (ret < 0) {
             error_report("%s: error while converting %s: %s",
                          out_filename, out_fmt, error_get_pretty(local_err));
@@ -1638,6 +1708,8 @@ out:
     qemu_progress_end();
     free_option_parameters(create_options);
     free_option_parameters(param);
+    qemu_opts_free(create_opts);
+    qemu_opts_del(opts);
     qemu_vfree(buf);
     if (sn_opts) {
         qemu_opts_del(sn_opts);
-- 
1.6.0.2




reply via email to

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