This patch will use QemuOpts related functions in block layer, add
a member bdrv_create_options to BlockDriver struct, it will return
a QemuOptsList pointer, which includes the image format's create
options.

And create options's primary consumer is block creating related functions,
so modify them together.

This patch also define a macro called STRINGIZER, it is used to convert
number to string.

v6->v7:
1) use osdep.h:stringify(), not redefining new macro.
2) preserve TODO comment.
3) fix typo: BLOCK_OPT_ENCRYPT->BLOCK_OPT_STATIC.
4) initialize disk_type even when opts is NULL.

v5->v6:
1) judge if opts == NULL in block layer create functions.
2) use bdrv_create_file(filename, NULL) in qcow_create and cow_create funtion.
3) made more readable while using qemu_opt_get_number.

Signed-off-by: Dong Xu Wang <wdon...@linux.vnet.ibm.com>
---
 block.c           |   91 +++++++++++++---------------
 block.h           |    5 +-
 block/cow.c       |   46 +++++++-------
 block/qcow.c      |   60 +++++++++---------
 block/qcow2.c     |  171 +++++++++++++++++++++++++++--------------------------
 block/qed.c       |   86 +++++++++++++-------------
 block/raw-posix.c |   65 ++++++++++-----------
 block/raw.c       |   30 +++++----
 block/sheepdog.c  |   75 +++++++++++------------
 block/vdi.c       |   69 +++++++++++-----------
 block/vmdk.c      |   74 ++++++++++++------------
 block/vpc.c       |   67 +++++++++++----------
 block/vvfat.c     |   11 ++--
 block_int.h       |    6 +-
 qemu-img.c        |   61 +++++++++----------
 15 files changed, 455 insertions(+), 462 deletions(-)

diff --git a/block.c b/block.c
index c05875f..e972a05 100644
--- a/block.c
+++ b/block.c
@@ -361,7 +361,7 @@ BlockDriver *bdrv_find_whitelisted_format(const char 
*format_name)
 typedef struct CreateCo {
     BlockDriver *drv;
     char *filename;
-    QEMUOptionParameter *options;
+    QemuOpts *opts;
     int ret;
 } CreateCo;
 
@@ -370,11 +370,11 @@ static void coroutine_fn bdrv_create_co_entry(void 
*opaque)
     CreateCo *cco = opaque;
     assert(cco->drv);
 
-    cco->ret = cco->drv->bdrv_create(cco->filename, cco->options);
+    cco->ret = cco->drv->bdrv_create(cco->filename, cco->opts);
 }
 
 int bdrv_create(BlockDriver *drv, const char* filename,
-    QEMUOptionParameter *options)
+    QemuOpts *opts)
 {
     int ret;
 
@@ -382,7 +382,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
     CreateCo cco = {
         .drv = drv,
         .filename = g_strdup(filename),
-        .options = options,
+        .opts = opts,
         .ret = NOT_DONE,
     };
 
@@ -409,7 +409,7 @@ out:
     return ret;
 }
 
-int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
+int bdrv_create_file(const char *filename, QemuOpts *opts)
 {
     BlockDriver *drv;
 
@@ -418,7 +418,7 @@ int bdrv_create_file(const char* filename, 
QEMUOptionParameter *options)
         return -ENOENT;
     }
 
-    return bdrv_create(drv, filename, options);
+    return bdrv_create(drv, filename, opts);
 }
 
 /*
@@ -795,7 +795,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, 
int flags,
         int64_t total_size;
         int is_protocol = 0;
         BlockDriver *bdrv_qcow2;
-        QEMUOptionParameter *options;
+        QemuOpts *opts;
         char backing_filename[PATH_MAX];
 
         /* if snapshot, we create a temporary backing file and open it
@@ -828,17 +828,16 @@ int bdrv_open(BlockDriverState *bs, const char *filename, 
int flags,
             return -errno;
 
         bdrv_qcow2 = bdrv_find_format("qcow2");
-        options = parse_option_parameters("", bdrv_qcow2->create_options, 
NULL);
+        opts = qemu_opts_create_nofail(bdrv_qcow2->bdrv_create_options);
 
-        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
-        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, 
backing_filename);
+        qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size);
+        qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, backing_filename);
         if (drv) {
-            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
-                drv->format_name);
+            qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, drv->format_name);
         }
 
-        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
-        free_option_parameters(options);
+        ret = bdrv_create(bdrv_qcow2, tmp_filename, opts);
+        qemu_opts_del(opts);
         if (ret < 0) {
             return ret;
         }
@@ -4412,8 +4411,10 @@ int bdrv_img_create(const char *filename, const char 
*fmt,
                     const char *base_filename, const char *base_fmt,
                     char *options, uint64_t img_size, int flags)
 {
-    QEMUOptionParameter *param = NULL, *create_options = NULL;
-    QEMUOptionParameter *backing_fmt, *backing_file, *size;
+    QemuOpts *opts = NULL;
+    QemuOptsList *create_options = NULL;
+    const char *backing_fmt, *backing_file;
+    int64_t size;
     BlockDriverState *bs = NULL;
     BlockDriver *drv, *proto_drv;
     BlockDriver *backing_drv = NULL;
@@ -4433,21 +4434,16 @@ int bdrv_img_create(const char *filename, const char 
*fmt,
         ret = -EINVAL;
         goto out;
     }
-
-    create_options = append_option_parameters(create_options,
-                                              drv->create_options);
-    create_options = append_option_parameters(create_options,
-                                              proto_drv->create_options);
-
+    create_options = append_opts_list(drv->bdrv_create_options,
+                                      proto_drv->bdrv_create_options);
     /* Create parameter list with default values */
-    param = parse_option_parameters("", create_options, param);
+    opts = qemu_opts_create_nofail(create_options);
 
-    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) {
+        if (qemu_opts_do_parse(opts, options, NULL) != 0) {
             error_report("Invalid options for file format '%s'.", fmt);
             ret = -EINVAL;
             goto out;
@@ -4455,7 +4451,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
     }
 
     if (base_filename) {
-        if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE,
+        if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE,
                                  base_filename)) {
             error_report("Backing file not supported for file format '%s'",
                          fmt);
@@ -4465,7 +4461,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
     }
 
     if (base_fmt) {
-        if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+        if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
             error_report("Backing file format not supported for file "
                          "format '%s'", fmt);
             ret = -EINVAL;
@@ -4473,9 +4469,9 @@ int bdrv_img_create(const char *filename, const char *fmt,
         }
     }
 
-    backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
-    if (backing_file && backing_file->value.s) {
-        if (!strcmp(filename, backing_file->value.s)) {
+    backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+    if (backing_file) {
+        if (!strcmp(filename, backing_file)) {
             error_report("Error: Trying to create an image with the "
                          "same filename as the backing file");
             ret = -EINVAL;
@@ -4483,12 +4479,11 @@ int bdrv_img_create(const char *filename, const char 
*fmt,
         }
     }
 
-    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);
+    backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
+    if (backing_fmt) {
+        backing_drv = bdrv_find_format(backing_fmt);
         if (!backing_drv) {
-            error_report("Unknown backing file format '%s'",
-                         backing_fmt->value.s);
+            error_report("Unknown backing file format '%s'", backing_fmt);
             ret = -EINVAL;
             goto out;
         }
@@ -4496,11 +4491,10 @@ int bdrv_img_create(const char *filename, const char 
*fmt,
 
     // 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) {
+    size = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, -1);
+    if (size == -1) {
+        if (backing_file) {
             uint64_t size;
-            char buf[32];
             int back_flags;
 
             /* backing files always opened read-only */
@@ -4509,16 +4503,15 @@ int bdrv_img_create(const char *filename, const char 
*fmt,
 
             bs = bdrv_new("");
 
-            ret = bdrv_open(bs, backing_file->value.s, back_flags, 
backing_drv);
+            ret = bdrv_open(bs, backing_file, back_flags, backing_drv);
             if (ret < 0) {
-                error_report("Could not open '%s'", backing_file->value.s);
+                error_report("Could not open '%s'", backing_file);
                 goto out;
             }
             bdrv_get_geometry(bs, &size);
             size *= 512;
 
-            snprintf(buf, sizeof(buf), "%" PRId64, size);
-            set_option_parameter(param, BLOCK_OPT_SIZE, buf);
+            qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size);
         } else {
             error_report("Image creation needs a size parameter");
             ret = -EINVAL;
@@ -4527,10 +4520,10 @@ int bdrv_img_create(const char *filename, const char 
*fmt,
     }
 
     printf("Formatting '%s', fmt=%s ", filename, fmt);
-    print_option_parameters(param);
+    qemu_opts_print(opts, NULL);
     puts("");
 
-    ret = bdrv_create(drv, filename, param);
+    ret = bdrv_create(drv, filename, opts);
 
     if (ret < 0) {
         if (ret == -ENOTSUP) {
@@ -4546,8 +4539,10 @@ int bdrv_img_create(const char *filename, const char 
*fmt,
     }
 
 out:
-    free_option_parameters(create_options);
-    free_option_parameters(param);
+    free_opts_list(create_options);
+    if (opts) {
+        qemu_opts_del(opts);
+    }
 
     if (bs) {
         bdrv_delete(bs);
diff --git a/block.h b/block.h
index 722c620..af3bdde 100644
--- a/block.h
+++ b/block.h
@@ -124,8 +124,8 @@ BlockDriver *bdrv_find_protocol(const char *filename);
 BlockDriver *bdrv_find_format(const char *format_name);
 BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
 int bdrv_create(BlockDriver *drv, const char* filename,
-    QEMUOptionParameter *options);
-int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
+    QemuOpts *options);
+int bdrv_create_file(const char *filename, QemuOpts *options);
 BlockDriverState *bdrv_new(const char *device_name);
 void bdrv_make_anon(BlockDriverState *bs);
 void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
@@ -430,5 +430,4 @@ typedef enum {
 
 #define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt)
 void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
-
 #endif
diff --git a/block/cow.c b/block/cow.c
index a5a00eb..1929a9f 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -255,7 +255,7 @@ static void cow_close(BlockDriverState *bs)
 {
 }
 
-static int cow_create(const char *filename, QEMUOptionParameter *options)
+static int cow_create(const char *filename, QemuOpts *opts)
 {
     struct cow_header_v2 cow_header;
     struct stat st;
@@ -264,17 +264,13 @@ static int cow_create(const char *filename, 
QEMUOptionParameter *options)
     int ret;
     BlockDriverState *cow_bs;
 
-    /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            image_sectors = options->value.n / 512;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
-            image_filename = options->value.s;
-        }
-        options++;
+    /* Read out opts */
+    if (opts) {
+        image_sectors = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0) / 512;
+        image_filename = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
     }
 
-    ret = bdrv_create_file(filename, options);
+    ret = bdrv_create_file(filename, NULL);
     if (ret < 0) {
         return ret;
     }
@@ -318,18 +314,22 @@ exit:
     return ret;
 }
 
-static QEMUOptionParameter cow_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    {
-        .name = BLOCK_OPT_BACKING_FILE,
-        .type = OPT_STRING,
-        .help = "File name of a base image"
-    },
-    { NULL }
+static QemuOptsList cow_create_opts = {
+    .name = "cow-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(cow_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_BACKING_FILE,
+            .type = QEMU_OPT_STRING,
+            .help = "File name of a base image"
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_cow = {
@@ -345,7 +345,7 @@ static BlockDriver bdrv_cow = {
     .bdrv_write             = cow_co_write,
     .bdrv_co_is_allocated   = cow_co_is_allocated,
 
-    .create_options = cow_create_options,
+    .bdrv_create_options    = &cow_create_opts,
 };
 
 static void bdrv_cow_init(void)
diff --git a/block/qcow.c b/block/qcow.c
index b239c82..d66859d 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -651,7 +651,7 @@ static void qcow_close(BlockDriverState *bs)
     error_free(s->migration_blocker);
 }
 
-static int qcow_create(const char *filename, QEMUOptionParameter *options)
+static int qcow_create(const char *filename, QemuOpts *opts)
 {
     int header_size, backing_filename_len, l1_size, shift, i;
     QCowHeader header;
@@ -662,19 +662,16 @@ static int qcow_create(const char *filename, 
QEMUOptionParameter *options)
     int ret;
     BlockDriverState *qcow_bs;
 
-    /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            total_size = options->value.n / 512;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
-            backing_file = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
-            flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
+    /* Read out opts */
+    if (opts) {
+        total_size = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0) / 512;
+        backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+        if (qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, 0)) {
+            flags |= BLOCK_FLAG_ENCRYPT;
         }
-        options++;
     }
 
-    ret = bdrv_create_file(filename, options);
+    ret = bdrv_create_file(filename, NULL);
     if (ret < 0) {
         return ret;
     }
@@ -851,24 +848,27 @@ static int qcow_get_info(BlockDriverState *bs, 
BlockDriverInfo *bdi)
     return 0;
 }
 
-
-static QEMUOptionParameter qcow_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    {
-        .name = BLOCK_OPT_BACKING_FILE,
-        .type = OPT_STRING,
-        .help = "File name of a base image"
-    },
-    {
-        .name = BLOCK_OPT_ENCRYPT,
-        .type = OPT_FLAG,
-        .help = "Encrypt the image"
-    },
-    { NULL }
+static QemuOptsList qcow_create_opts = {
+    .name = "qcow-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(qcow_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_BACKING_FILE,
+            .type = QEMU_OPT_STRING,
+            .help = "File name of a base image"
+        },
+        {
+            .name = BLOCK_OPT_ENCRYPT,
+            .type = QEMU_OPT_BOOL,
+            .help = "Encrypt the image"
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_qcow = {
@@ -889,7 +889,7 @@ static BlockDriver bdrv_qcow = {
     .bdrv_write_compressed  = qcow_write_compressed,
     .bdrv_get_info          = qcow_get_info,
 
-    .create_options = qcow_create_options,
+    .bdrv_create_options    = &qcow_create_opts,
 };
 
 static void bdrv_qcow_init(void)
diff --git a/block/qcow2.c b/block/qcow2.c
index c1ff31f..38f467c 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1180,7 +1180,7 @@ static int preallocate(BlockDriverState *bs)
 static int qcow2_create2(const char *filename, int64_t total_size,
                          const char *backing_file, const char *backing_format,
                          int flags, size_t cluster_size, int prealloc,
-                         QEMUOptionParameter *options, int version)
+                         int version)
 {
     /* Calculate cluster_bits */
     int cluster_bits;
@@ -1211,7 +1211,7 @@ static int qcow2_create2(const char *filename, int64_t 
total_size,
     uint8_t* refcount_table;
     int ret;
 
-    ret = bdrv_create_file(filename, options);
+    ret = bdrv_create_file(filename, NULL);
     if (ret < 0) {
         return ret;
     }
@@ -1314,7 +1314,7 @@ out:
     return ret;
 }
 
-static int qcow2_create(const char *filename, QEMUOptionParameter *options)
+static int qcow2_create(const char *filename, QemuOpts *opts)
 {
     const char *backing_file = NULL;
     const char *backing_fmt = NULL;
@@ -1323,45 +1323,43 @@ static int qcow2_create(const char *filename, 
QEMUOptionParameter *options)
     size_t cluster_size = DEFAULT_CLUSTER_SIZE;
     int prealloc = 0;
     int version = 2;
+    const char *buf;
 
     /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            sectors = options->value.n / 512;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
-            backing_file = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) {
-            backing_fmt = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
-            flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
-        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
-            if (options->value.n) {
-                cluster_size = options->value.n;
-            }
-        } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
-            if (!options->value.s || !strcmp(options->value.s, "off")) {
-                prealloc = 0;
-            } else if (!strcmp(options->value.s, "metadata")) {
-                prealloc = 1;
-            } else {
-                fprintf(stderr, "Invalid preallocation mode: '%s'\n",
-                    options->value.s);
-                return -EINVAL;
-            }
-        } else if (!strcmp(options->name, BLOCK_OPT_COMPAT_LEVEL)) {
-            if (!options->value.s || !strcmp(options->value.s, "0.10")) {
-                version = 2;
-            } else if (!strcmp(options->value.s, "1.1")) {
-                version = 3;
-            } else {
-                fprintf(stderr, "Invalid compatibility level: '%s'\n",
-                    options->value.s);
-                return -EINVAL;
-            }
-        } else if (!strcmp(options->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
-            flags |= options->value.n ? BLOCK_FLAG_LAZY_REFCOUNTS : 0;
+    if (opts) {
+        sectors = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0) / 512;
+        backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+        backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
+        if (qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, 0)) {
+            flags |= BLOCK_FLAG_ENCRYPT;
+        }
+        cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,
+                                         DEFAULT_CLUSTER_SIZE);
+        buf = qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
+        if (!buf || !strcmp(buf, "off")) {
+            prealloc = 0;
+        } else if (!strcmp(buf, "metadata")) {
+            prealloc = 1;
+        } else {
+            fprintf(stderr, "Invalid preallocation mode: '%s'\n",
+                buf);
+            return -EINVAL;
+        }
+
+        buf = qemu_opt_get(opts, BLOCK_OPT_COMPAT_LEVEL);
+        if (!buf || !strcmp(buf, "0.10")) {
+            version = 2;
+        } else if (!strcmp(buf, "1.1")) {
+            version = 3;
+        } else {
+            fprintf(stderr, "Invalid compatibility level: '%s'\n",
+                buf);
+            return -EINVAL;
+        }
+
+        if (qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS, 0)) {
+            flags |= BLOCK_FLAG_LAZY_REFCOUNTS;
         }
-        options++;
     }
 
     if (backing_file && prealloc) {
@@ -1377,7 +1375,7 @@ static int qcow2_create(const char *filename, 
QEMUOptionParameter *options)
     }
 
     return qcow2_create2(filename, sectors, backing_file, backing_fmt, flags,
-                         cluster_size, prealloc, options, version);
+                         cluster_size, prealloc, version);
 }
 
 static int qcow2_make_empty(BlockDriverState *bs)
@@ -1638,49 +1636,53 @@ static int qcow2_load_vmstate(BlockDriverState *bs, 
uint8_t *buf,
     return ret;
 }
 
-static QEMUOptionParameter qcow2_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    {
-        .name = BLOCK_OPT_COMPAT_LEVEL,
-        .type = OPT_STRING,
-        .help = "Compatibility level (0.10 or 1.1)"
-    },
-    {
-        .name = BLOCK_OPT_BACKING_FILE,
-        .type = OPT_STRING,
-        .help = "File name of a base image"
-    },
-    {
-        .name = BLOCK_OPT_BACKING_FMT,
-        .type = OPT_STRING,
-        .help = "Image format of the base image"
-    },
-    {
-        .name = BLOCK_OPT_ENCRYPT,
-        .type = OPT_FLAG,
-        .help = "Encrypt the image"
-    },
-    {
-        .name = BLOCK_OPT_CLUSTER_SIZE,
-        .type = OPT_SIZE,
-        .help = "qcow2 cluster size",
-        .value = { .n = DEFAULT_CLUSTER_SIZE },
-    },
-    {
-        .name = BLOCK_OPT_PREALLOC,
-        .type = OPT_STRING,
-        .help = "Preallocation mode (allowed values: off, metadata)"
-    },
-    {
-        .name = BLOCK_OPT_LAZY_REFCOUNTS,
-        .type = OPT_FLAG,
-        .help = "Postpone refcount updates",
-    },
-    { NULL }
+static QemuOptsList qcow2_create_opts = {
+    .name = "qcow2-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(qcow2_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_COMPAT_LEVEL,
+            .type = QEMU_OPT_STRING,
+            .help = "Compatibility level (0.10 or 1.1)"
+        },
+        {
+            .name = BLOCK_OPT_BACKING_FILE,
+            .type = QEMU_OPT_STRING,
+            .help = "File name of a base image"
+        },
+        {
+            .name = BLOCK_OPT_BACKING_FMT,
+            .type = QEMU_OPT_STRING,
+            .help = "Image format of the base image"
+        },
+        {
+            .name = BLOCK_OPT_ENCRYPT,
+            .type = QEMU_OPT_BOOL,
+            .help = "Encrypt the image"
+        },
+        {
+            .name = BLOCK_OPT_CLUSTER_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "qcow2 cluster size",
+            .def_print_str = stringify(DEFAULT_CLUSTER_SIZE)
+        },
+        {
+            .name = BLOCK_OPT_PREALLOC,
+            .type = QEMU_OPT_STRING,
+            .help = "Preallocation mode (allowed values: off, metadata)"
+        },
+        {
+            .name = BLOCK_OPT_LAZY_REFCOUNTS,
+            .type = QEMU_OPT_BOOL,
+            .help = "Postpone refcount updates",
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_qcow2 = {
@@ -1718,8 +1720,9 @@ static BlockDriver bdrv_qcow2 = {
 
     .bdrv_invalidate_cache      = qcow2_invalidate_cache,
 
-    .create_options = qcow2_create_options,
     .bdrv_check = qcow2_check,
+
+    .bdrv_create_options    = &qcow2_create_opts,
 };
 
 static void bdrv_qcow2_init(void)
diff --git a/block/qed.c b/block/qed.c
index 0b5374a..6d86954 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -603,7 +603,7 @@ out:
     return ret;
 }
 
-static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options)
+static int bdrv_qed_create(const char *filename, QemuOpts *opts)
 {
     uint64_t image_size = 0;
     uint32_t cluster_size = QED_DEFAULT_CLUSTER_SIZE;
@@ -611,23 +611,15 @@ static int bdrv_qed_create(const char *filename, 
QEMUOptionParameter *options)
     const char *backing_file = NULL;
     const char *backing_fmt = NULL;
 
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            image_size = options->value.n;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
-            backing_file = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) {
-            backing_fmt = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
-            if (options->value.n) {
-                cluster_size = options->value.n;
-            }
-        } else if (!strcmp(options->name, BLOCK_OPT_TABLE_SIZE)) {
-            if (options->value.n) {
-                table_size = options->value.n;
-            }
-        }
-        options++;
+    if (opts) {
+        image_size = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0);
+        backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+        backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
+        cluster_size = qemu_opt_get_size(opts,
+                                         BLOCK_OPT_CLUSTER_SIZE,
+                                         QED_DEFAULT_CLUSTER_SIZE);
+        table_size = qemu_opt_get_size(opts, BLOCK_OPT_TABLE_SIZE,
+                                       QED_DEFAULT_TABLE_SIZE);
     }
 
     if (!qed_is_cluster_size_valid(cluster_size)) {
@@ -1537,36 +1529,44 @@ static int bdrv_qed_check(BlockDriverState *bs, 
BdrvCheckResult *result,
     return qed_check(s, result, !!fix);
 }
 
-static QEMUOptionParameter qed_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size (in bytes)"
-    }, {
-        .name = BLOCK_OPT_BACKING_FILE,
-        .type = OPT_STRING,
-        .help = "File name of a base image"
-    }, {
-        .name = BLOCK_OPT_BACKING_FMT,
-        .type = OPT_STRING,
-        .help = "Image format of the base image"
-    }, {
-        .name = BLOCK_OPT_CLUSTER_SIZE,
-        .type = OPT_SIZE,
-        .help = "Cluster size (in bytes)",
-        .value = { .n = QED_DEFAULT_CLUSTER_SIZE },
-    }, {
-        .name = BLOCK_OPT_TABLE_SIZE,
-        .type = OPT_SIZE,
-        .help = "L1/L2 table size (in clusters)"
-    },
-    { /* end of list */ }
+static QemuOptsList qed_create_opts = {
+    .name = "qed-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(qed_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_BACKING_FILE,
+            .type = QEMU_OPT_STRING,
+            .help = "File name of a base image"
+        },
+        {
+            .name = BLOCK_OPT_BACKING_FMT,
+            .type = QEMU_OPT_STRING,
+            .help = "Image format of the base image"
+        },
+        {
+            .name = BLOCK_OPT_CLUSTER_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "Cluster size (in bytes)",
+            .def_print_str = stringify(QED_DEFAULT_CLUSTER_SIZE),
+        },
+        {
+            .name = BLOCK_OPT_TABLE_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "L1/L2 table size (in clusters)"
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_qed = {
     .format_name              = "qed",
     .instance_size            = sizeof(BDRVQEDState),
-    .create_options           = qed_create_options,
+    .bdrv_create_options      = &qed_create_opts,
 
     .bdrv_probe               = bdrv_qed_probe,
     .bdrv_rebind              = bdrv_qed_rebind,
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 550c81f..6b23e90 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -121,6 +121,19 @@
 
 #define MAX_BLOCKSIZE  4096
 
+static QemuOptsList file_proto_create_opts = {
+    .name = "file-proto-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(file_proto_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "Virtual disk size"
+        },
+        { /* end of list */ }
+    }
+};
+
 typedef struct BDRVRawState {
     int fd;
     int type;
@@ -964,18 +977,15 @@ static int64_t 
raw_get_allocated_file_size(BlockDriverState *bs)
     return (int64_t)st.st_blocks * 512;
 }
 
-static int raw_create(const char *filename, QEMUOptionParameter *options)
+static int raw_create(const char *filename, QemuOpts *opts)
 {
     int fd;
     int result = 0;
     int64_t total_size = 0;
 
-    /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            total_size = options->value.n / BDRV_SECTOR_SIZE;
-        }
-        options++;
+    if (opts) {
+        total_size =
+            qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
     }
 
     fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
@@ -1126,15 +1136,6 @@ static coroutine_fn int raw_co_discard(BlockDriverState 
*bs,
     return 0;
 }
 
-static QEMUOptionParameter raw_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    { NULL }
-};
-
 static BlockDriver bdrv_file = {
     .format_name = "file",
     .protocol_name = "file",
@@ -1157,8 +1158,7 @@ static BlockDriver bdrv_file = {
     .bdrv_getlength = raw_getlength,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
-
-    .create_options = raw_create_options,
+    .bdrv_create_options = &file_proto_create_opts,
 };
 
 /***********************************************/
@@ -1371,19 +1371,16 @@ static int fd_open(BlockDriverState *bs)
 
 #endif /* !linux && !FreeBSD */
 
-static int hdev_create(const char *filename, QEMUOptionParameter *options)
+static int hdev_create(const char *filename, QemuOpts *opts)
 {
     int fd;
     int ret = 0;
     struct stat stat_buf;
     int64_t total_size = 0;
 
-    /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, "size")) {
-            total_size = options->value.n / BDRV_SECTOR_SIZE;
-        }
-        options++;
+    if (opts) {
+        total_size =
+            qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
     }
 
     fd = qemu_open(filename, O_WRONLY | O_BINARY);
@@ -1408,7 +1405,7 @@ static int hdev_has_zero_init(BlockDriverState *bs)
 
 static BlockDriver bdrv_host_device = {
     .format_name        = "host_device",
-    .protocol_name        = "host_device",
+    .protocol_name      = "host_device",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device  = hdev_probe_device,
     .bdrv_file_open     = hdev_open,
@@ -1417,17 +1414,17 @@ static BlockDriver bdrv_host_device = {
     .bdrv_reopen_commit  = raw_reopen_commit,
     .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
-    .create_options     = raw_create_options,
     .bdrv_has_zero_init = hdev_has_zero_init,
 
-    .bdrv_aio_readv    = raw_aio_readv,
-    .bdrv_aio_writev   = raw_aio_writev,
-    .bdrv_aio_flush    = raw_aio_flush,
+    .bdrv_aio_readv     = raw_aio_readv,
+    .bdrv_aio_writev    = raw_aio_writev,
+    .bdrv_aio_flush     = raw_aio_flush,
 
     .bdrv_truncate      = raw_truncate,
-    .bdrv_getlength    = raw_getlength,
+    .bdrv_getlength     = raw_getlength,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
+    .bdrv_create_options = &file_proto_create_opts,
 
     /* generic scsi device */
 #ifdef __linux__
@@ -1541,7 +1538,6 @@ static BlockDriver bdrv_host_floppy = {
     .bdrv_reopen_commit  = raw_reopen_commit,
     .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
-    .create_options     = raw_create_options,
     .bdrv_has_zero_init = hdev_has_zero_init,
 
     .bdrv_aio_readv     = raw_aio_readv,
@@ -1557,6 +1553,7 @@ static BlockDriver bdrv_host_floppy = {
     .bdrv_is_inserted   = floppy_is_inserted,
     .bdrv_media_changed = floppy_media_changed,
     .bdrv_eject         = floppy_eject,
+    .bdrv_create_options = &file_proto_create_opts,
 };
 
 static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
@@ -1643,7 +1640,6 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_reopen_commit  = raw_reopen_commit,
     .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
-    .create_options     = raw_create_options,
     .bdrv_has_zero_init = hdev_has_zero_init,
 
     .bdrv_aio_readv     = raw_aio_readv,
@@ -1663,6 +1659,8 @@ static BlockDriver bdrv_host_cdrom = {
     /* generic scsi device */
     .bdrv_ioctl         = hdev_ioctl,
     .bdrv_aio_ioctl     = hdev_aio_ioctl,
+
+    .bdrv_create_options = &file_proto_create_opts,
 };
 #endif /* __linux__ */
 
@@ -1765,7 +1763,6 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_reopen_commit  = raw_reopen_commit,
     .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
-    .create_options     = raw_create_options,
     .bdrv_has_zero_init = hdev_has_zero_init,
 
     .bdrv_aio_readv     = raw_aio_readv,
diff --git a/block/raw.c b/block/raw.c
index 253e949..769d04d 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -95,18 +95,22 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
    return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque);
 }
 
-static int raw_create(const char *filename, QEMUOptionParameter *options)
-{
-    return bdrv_create_file(filename, options);
-}
-
-static QEMUOptionParameter raw_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    { NULL }
+static int raw_create(const char *filename, QemuOpts *opts)
+{
+    return bdrv_create_file(filename, opts);
+}
+
+static QemuOptsList raw_create_opts = {
+    .name = "raw-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
+        { /* end of list */ }
+    }
 };
 
 static int raw_has_zero_init(BlockDriverState *bs)
@@ -143,8 +147,8 @@ static BlockDriver bdrv_raw = {
     .bdrv_aio_ioctl     = raw_aio_ioctl,
 
     .bdrv_create        = raw_create,
-    .create_options     = raw_create_options,
     .bdrv_has_zero_init = raw_has_zero_init,
+    .bdrv_create_options = &raw_create_opts,
 };
 
 static void bdrv_raw_init(void)
diff --git a/block/sheepdog.c b/block/sheepdog.c
index a48f58c..b0c5989 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1261,12 +1261,12 @@ out:
     return ret;
 }
 
-static int sd_create(const char *filename, QEMUOptionParameter *options)
+static int sd_create(const char *filename, QemuOpts *opts)
 {
     int ret = 0;
     uint32_t vid = 0, base_vid = 0;
     int64_t vdi_size = 0;
-    char *backing_file = NULL;
+    const char *backing_file = NULL, *buf = NULL;
     BDRVSheepdogState *s;
     char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
     uint32_t snapid;
@@ -1285,26 +1285,20 @@ static int sd_create(const char *filename, 
QEMUOptionParameter *options)
         goto out;
     }
 
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            vdi_size = options->value.n;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
-            backing_file = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
-            if (!options->value.s || !strcmp(options->value.s, "off")) {
-                prealloc = false;
-            } else if (!strcmp(options->value.s, "full")) {
-                prealloc = true;
-            } else {
-                error_report("Invalid preallocation mode: '%s'",
-                             options->value.s);
-                ret = -EINVAL;
-                goto out;
-            }
+    if (opts) {
+        vdi_size = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0);
+        backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+        buf = qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
+        if (!buf || !strcmp(buf, "off")) {
+            prealloc = false;
+        } else if (!strcmp(buf, "full")) {
+            prealloc = true;
+        } else {
+            error_report("Invalid preallocation mode: '%s'", buf);
+            ret = -EINVAL;
+            goto out;
         }
-        options++;
     }
-
     if (vdi_size > SD_MAX_VDI_SIZE) {
         error_report("too big image size");
         ret = -EINVAL;
@@ -2040,24 +2034,27 @@ static int sd_load_vmstate(BlockDriverState *bs, 
uint8_t *data,
     return do_load_save_vmstate(s, data, pos, size, 1);
 }
 
-
-static QEMUOptionParameter sd_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    {
-        .name = BLOCK_OPT_BACKING_FILE,
-        .type = OPT_STRING,
-        .help = "File name of a base image"
-    },
-    {
-        .name = BLOCK_OPT_PREALLOC,
-        .type = OPT_STRING,
-        .help = "Preallocation mode (allowed values: off, full)"
-    },
-    { NULL }
+static QemuOptsList sd_create_opts = {
+    .name = "sheepdog-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(sd_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_BACKING_FILE,
+            .type = QEMU_OPT_STRING,
+            .help = "File name of a base image"
+        },
+        {
+            .name = BLOCK_OPT_PREALLOC,
+            .type = QEMU_OPT_STRING,
+            .help = "Preallocation mode (allowed values: off, full)"
+        },
+        { /* end of list */ }
+    }
 };
 
 BlockDriver bdrv_sheepdog = {
@@ -2082,7 +2079,7 @@ BlockDriver bdrv_sheepdog = {
     .bdrv_save_vmstate  = sd_save_vmstate,
     .bdrv_load_vmstate  = sd_load_vmstate,
 
-    .create_options = sd_create_options,
+    .bdrv_create_options = &sd_create_opts,
 };
 
 static void bdrv_sheepdog_init(void)
diff --git a/block/vdi.c b/block/vdi.c
index c8330b7..ec19d74 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -620,7 +620,7 @@ static int vdi_co_write(BlockDriverState *bs,
     return ret;
 }
 
-static int vdi_create(const char *filename, QEMUOptionParameter *options)
+static int vdi_create(const char *filename, QemuOpts *opts)
 {
     int fd;
     int result = 0;
@@ -635,24 +635,19 @@ static int vdi_create(const char *filename, 
QEMUOptionParameter *options)
     logout("\n");
 
     /* Read out options. */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            bytes = options->value.n;
+    if (opts) {
+        bytes = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0);
 #if defined(CONFIG_VDI_BLOCK_SIZE)
-        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
-            if (options->value.n) {
-                /* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */
-                block_size = options->value.n;
-            }
+        /* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */
+        block_size = qemu_opt_get_size(opts,
+                                       BLOCK_OPT_CLUSTER_SIZE,
+                                       DEFAULT_CLUSTER_SIZE);
 #endif
 #if defined(CONFIG_VDI_STATIC_IMAGE)
-        } else if (!strcmp(options->name, BLOCK_OPT_STATIC)) {
-            if (options->value.n) {
-                image_type = VDI_TYPE_STATIC;
-            }
-#endif
+        if (qemu_opt_get_bool(opts, BLOCK_OPT_STATIC, 0)) {
+            image_type = VDI_TYPE_STATIC;
         }
-        options++;
+#endif
     }
 
     fd = qemu_open(filename,
@@ -733,29 +728,33 @@ static void vdi_close(BlockDriverState *bs)
     error_free(s->migration_blocker);
 }
 
-static QEMUOptionParameter vdi_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
+static QemuOptsList vdi_create_opts = {
+    .name = "vdi-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(vdi_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
 #if defined(CONFIG_VDI_BLOCK_SIZE)
-    {
-        .name = BLOCK_OPT_CLUSTER_SIZE,
-        .type = OPT_SIZE,
-        .help = "VDI cluster (block) size",
-        .value = { .n = DEFAULT_CLUSTER_SIZE },
-    },
+        {
+            .name = BLOCK_OPT_CLUSTER_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "VDI cluster (block) size",
+            .def_print_str = STRINGIZER(DEFAULT_CLUSTER_SIZE)
+        },
 #endif
 #if defined(CONFIG_VDI_STATIC_IMAGE)
-    {
-        .name = BLOCK_OPT_STATIC,
-        .type = OPT_FLAG,
-        .help = "VDI static (pre-allocated) image"
-    },
+        {
+            .name = BLOCK_OPT_STATIC,
+            .type = QEMU_OPT_BOOL,
+            .help = "VDI static (pre-allocated) image"
+        },
 #endif
-    /* TODO: An additional option to set UUID values might be useful. */
-    { NULL }
+        /* TODO: An additional option to set UUID values might be useful. */
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_vdi = {
@@ -776,7 +775,7 @@ static BlockDriver bdrv_vdi = {
 
     .bdrv_get_info = vdi_get_info,
 
-    .create_options = vdi_create_options,
+    .bdrv_create_options = &vdi_create_opts,
     .bdrv_check = vdi_check,
 };
 
diff --git a/block/vmdk.c b/block/vmdk.c
index 51398c0..1f4d36b 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1437,7 +1437,7 @@ static int relative_path(char *dest, int dest_size,
     return 0;
 }
 
-static int vmdk_create(const char *filename, QEMUOptionParameter *options)
+static int vmdk_create(const char *filename, QemuOpts *opts)
 {
     int fd, idx = 0;
     char desc[BUF_SIZE];
@@ -1476,18 +1476,14 @@ static int vmdk_create(const char *filename, 
QEMUOptionParameter *options)
     if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) {
         return -EINVAL;
     }
-    /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            total_size = options->value.n;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
-            backing_file = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
-            flags |= options->value.n ? BLOCK_FLAG_COMPAT6 : 0;
-        } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
-            fmt = options->value.s;
+    /* Read out opts */
+    if (opts) {
+        total_size = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0);
+        backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+        if (qemu_opt_get_bool(opts, BLOCK_OPT_COMPAT6, 0)) {
+            flags |= BLOCK_FLAG_COMPAT6;
         }
-        options++;
+        fmt = qemu_opt_get(opts, BLOCK_OPT_SUBFMT);
     }
     if (!fmt) {
         /* Default format to monolithicSparse */
@@ -1654,30 +1650,34 @@ static int64_t 
vmdk_get_allocated_file_size(BlockDriverState *bs)
     return ret;
 }
 
-static QEMUOptionParameter vmdk_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    {
-        .name = BLOCK_OPT_BACKING_FILE,
-        .type = OPT_STRING,
-        .help = "File name of a base image"
-    },
-    {
-        .name = BLOCK_OPT_COMPAT6,
-        .type = OPT_FLAG,
-        .help = "VMDK version 6 image"
-    },
-    {
-        .name = BLOCK_OPT_SUBFMT,
-        .type = OPT_STRING,
-        .help =
-            "VMDK flat extent format, can be one of "
-            "{monolithicSparse (default) | monolithicFlat | 
twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
-    },
-    { NULL }
+static QemuOptsList vmdk_create_opts = {
+    .name = "vmdk-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_BACKING_FILE,
+            .type = QEMU_OPT_STRING,
+            .help = "File name of a base image"
+        },
+        {
+            .name = BLOCK_OPT_COMPAT6,
+            .type = QEMU_OPT_BOOL,
+            .help = "VMDK version 6 image"
+        },
+        {
+            .name = BLOCK_OPT_SUBFMT,
+            .type = QEMU_OPT_STRING,
+            .help =
+                "VMDK flat extent format, can be one of "
+                "{monolithicSparse (default) | monolithicFlat | 
twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_vmdk = {
@@ -1694,7 +1694,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_co_is_allocated   = vmdk_co_is_allocated,
     .bdrv_get_allocated_file_size  = vmdk_get_allocated_file_size,
 
-    .create_options = vmdk_create_options,
+    .bdrv_create_options = &vmdk_create_opts,
 };
 
 static void bdrv_vmdk_init(void)
diff --git a/block/vpc.c b/block/vpc.c
index b6bf52f..732cdde 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -653,34 +653,33 @@ static int create_fixed_disk(int fd, uint8_t *buf, 
int64_t total_size)
     return ret;
 }
 
-static int vpc_create(const char *filename, QEMUOptionParameter *options)
+static int vpc_create(const char *filename, QemuOpts *opts)
 {
     uint8_t buf[1024];
     struct vhd_footer *footer = (struct vhd_footer *) buf;
-    QEMUOptionParameter *disk_type_param;
+    const char *disk_type_param = NULL;
     int fd, i;
     uint16_t cyls = 0;
     uint8_t heads = 0;
     uint8_t secs_per_cyl = 0;
     int64_t total_sectors;
-    int64_t total_size;
-    int disk_type;
+    int64_t total_size = 0;
+    int disk_type = VHD_DYNAMIC;
     int ret = -EIO;
 
-    /* Read out options */
-    total_size = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n;
-
-    disk_type_param = get_option_parameter(options, BLOCK_OPT_SUBFMT);
-    if (disk_type_param && disk_type_param->value.s) {
-        if (!strcmp(disk_type_param->value.s, "dynamic")) {
-            disk_type = VHD_DYNAMIC;
-        } else if (!strcmp(disk_type_param->value.s, "fixed")) {
-            disk_type = VHD_FIXED;
-        } else {
-            return -EINVAL;
+    /* Read out opts */
+    if (opts) {
+        total_size = qemu_opt_get_number(opts, BLOCK_OPT_SIZE, 0);
+        disk_type_param = qemu_opt_get(opts, BLOCK_OPT_SUBFMT);
+        if (disk_type_param) {
+            if (!strcmp(disk_type_param, "dynamic")) {
+                disk_type = VHD_DYNAMIC;
+            } else if (!strcmp(disk_type_param, "fixed")) {
+                disk_type = VHD_FIXED;
+            } else {
+                return -EINVAL;
+            }
         }
-    } else {
-        disk_type = VHD_DYNAMIC;
     }
 
     /* Create the file */
@@ -766,20 +765,24 @@ static void vpc_close(BlockDriverState *bs)
     error_free(s->migration_blocker);
 }
 
-static QEMUOptionParameter vpc_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    {
-        .name = BLOCK_OPT_SUBFMT,
-        .type = OPT_STRING,
-        .help =
-            "Type of virtual hard disk format. Supported formats are "
-            "{dynamic (default) | fixed} "
-    },
-    { NULL }
+static QemuOptsList vpc_create_opts = {
+    .name = "vpc-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(vpc_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_NUMBER,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_SUBFMT,
+            .type = OPT_STRING,
+            .help =
+                "Type of virtual hard disk format. Supported formats are "
+                "{dynamic (default) | fixed} "
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_vpc = {
@@ -795,7 +798,7 @@ static BlockDriver bdrv_vpc = {
     .bdrv_read              = vpc_co_read,
     .bdrv_write             = vpc_co_write,
 
-    .create_options = vpc_create_options,
+    .bdrv_create_options = &vpc_create_opts,
 };
 
 static void bdrv_vpc_init(void)
diff --git a/block/vvfat.c b/block/vvfat.c
index 59d3c5b..0965d4c 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2806,7 +2806,7 @@ static BlockDriver vvfat_write_target = {
 static int enable_write_target(BDRVVVFATState *s)
 {
     BlockDriver *bdrv_qcow;
-    QEMUOptionParameter *options;
+    QemuOpts *opts;
     int ret;
     int size = sector2cluster(s, s->sector_count);
     s->used_clusters = calloc(size, 1);
@@ -2822,12 +2822,13 @@ static int enable_write_target(BDRVVVFATState *s)
     }
 
     bdrv_qcow = bdrv_find_format("qcow");
-    options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
-    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
-    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
+    opts = qemu_opts_create_nofail(bdrv_qcow->bdrv_create_options);
+    qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512);
+    qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:");
 
-    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
+    if (bdrv_create(bdrv_qcow, s->qcow_filename, opts) < 0) {
        return -1;
+    }
 
     s->qcow = bdrv_new("");
     if (s->qcow == NULL) {
diff --git a/block_int.h b/block_int.h
index 9deedb8..63f1a07 100644
--- a/block_int.h
+++ b/block_int.h
@@ -88,7 +88,7 @@ struct BlockDriver {
                       const uint8_t *buf, int nb_sectors);
     void (*bdrv_close)(BlockDriverState *bs);
     void (*bdrv_rebind)(BlockDriverState *bs);
-    int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
+    int (*bdrv_create)(const char *filename, QemuOpts *options);
     int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
     int (*bdrv_make_empty)(BlockDriverState *bs);
     /* aio */
@@ -177,9 +177,7 @@ struct BlockDriver {
         unsigned long int req, void *buf,
         BlockDriverCompletionFunc *cb, void *opaque);
 
-    /* List of options for creating images, terminated by name == NULL */
-    QEMUOptionParameter *create_options;
-
+    QemuOptsList *bdrv_create_options;
 
     /*
      * Returns 0 for completed check, -errno for internal errors.
diff --git a/qemu-img.c b/qemu-img.c
index dcd390d..c4b006f 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -200,7 +200,7 @@ static int read_password(char *buf, int buf_size)
 static int print_block_option_help(const char *filename, const char *fmt)
 {
     BlockDriver *drv, *proto_drv;
-    QEMUOptionParameter *create_options = NULL;
+    QemuOptsList *create_options = NULL;
 
     /* Find driver and parse its options */
     drv = bdrv_find_format(fmt);
@@ -215,12 +215,10 @@ 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);
-    free_option_parameters(create_options);
+    create_options = append_opts_list(drv->bdrv_create_options,
+                                      proto_drv->bdrv_create_options);
+    print_opts_list(create_options);
+    free_opts_list(create_options);
     return 0;
 }
 
@@ -271,19 +269,19 @@ fail:
     return NULL;
 }
 
-static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
+static int add_old_style_options(const char *fmt, QemuOpts *list,
                                  const char *base_filename,
                                  const char *base_fmt)
 {
     if (base_filename) {
-        if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) 
{
+        if (qemu_opt_set(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 (qemu_opt_set(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
             error_report("Backing file format not supported for file "
                          "format '%s'", fmt);
             return -1;
@@ -670,8 +668,9 @@ static int img_convert(int argc, char **argv)
     uint8_t * buf = NULL;
     const uint8_t *buf1;
     BlockDriverInfo bdi;
-    QEMUOptionParameter *param = NULL, *create_options = NULL;
-    QEMUOptionParameter *out_baseimg_param;
+    QemuOpts *param = NULL;
+    QemuOptsList *create_options = NULL;
+    const char *out_baseimg_param;
     char *options = NULL;
     const char *snapshot_name = NULL;
     float local_progress = 0;
@@ -806,40 +805,36 @@ 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);
+    create_options = append_opts_list(drv->bdrv_create_options,
+                                      proto_drv->bdrv_create_options);
 
     if (options) {
-        param = parse_option_parameters(options, create_options, param);
-        if (param == NULL) {
+        if (qemu_opts_do_parse(param, options, NULL) != 0) {
             error_report("Invalid options for file format '%s'.", out_fmt);
             ret = -1;
             goto out;
         }
     } else {
-        param = parse_option_parameters("", create_options, param);
+        param = qemu_opts_create_nofail(create_options);
     }
-
-    set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
+    qemu_opt_set_number(param, BLOCK_OPT_SIZE, total_sectors * 512);
     ret = add_old_style_options(out_fmt, param, 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);
+    out_baseimg_param = qemu_opt_get(param, BLOCK_OPT_BACKING_FILE);
     if (out_baseimg_param) {
-        out_baseimg = out_baseimg_param->value.s;
+        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);
+        bool encryption =
+            qemu_opt_get_bool(param, BLOCK_OPT_ENCRYPT, false);
+        const char *preallocation =
+            qemu_opt_get(param, BLOCK_OPT_PREALLOC);
 
         if (!drv->bdrv_write_compressed) {
             error_report("Compression not supported for this file format");
@@ -847,15 +842,15 @@ static int img_convert(int argc, char **argv)
             goto out;
         }
 
-        if (encryption && encryption->value.n) {
+        if (encryption) {
             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"))
+        if (preallocation
+            && strcmp(preallocation, "off"))
         {
             error_report("Compression and preallocation not supported at "
                          "the same time");
@@ -1073,8 +1068,10 @@ static int img_convert(int argc, char **argv)
     }
 out:
     qemu_progress_end();
-    free_option_parameters(create_options);
-    free_option_parameters(param);
+    free_opts_list(create_options);
+    if (param) {
+        qemu_opts_del(param);
+    }
     qemu_vfree(buf);
     if (out_bs) {
         bdrv_delete(out_bs);
-- 
1.7.1


Reply via email to