All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser
@ 2013-04-10  6:25 Dong Xu Wang
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 1/6] add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print Dong Xu Wang
                   ` (7 more replies)
  0 siblings, 8 replies; 16+ messages in thread
From: Dong Xu Wang @ 2013-04-10  6:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, Dong Xu Wang, wdongxu, armbru, stefanha

These patches will replace QEMUOptionParameter with QemuOpts. Change logs
please go to each patch's commit message.

Dong Xu Wang (6):
  add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print
  avoid duplication of default value in QemuOpts
  Create four QemuOptsList related functions
  create some QemuOpts functons
  Use QemuOpts support in block layer
  remove QEMUOptionParameter related functions and struct

 block.c                   |  98 ++++----
 block/cow.c               |  46 ++--
 block/gluster.c           |  37 ++--
 block/iscsi.c             |  35 ++-
 block/qcow.c              |  61 +++--
 block/qcow2.c             | 173 ++++++++-------
 block/qed.c               |  86 ++++---
 block/qed.h               |   2 +-
 block/raw-posix.c         |  59 +++--
 block/raw-win32.c         |  31 +--
 block/raw.c               |  30 +--
 block/rbd.c               |  62 +++---
 block/sheepdog.c          |  79 ++++---
 block/vdi.c               |  70 +++---
 block/vmdk.c              |  90 ++++----
 block/vpc.c               |  57 ++---
 block/vvfat.c             |  11 +-
 include/block/block.h     |   5 +-
 include/block/block_int.h |   6 +-
 include/qemu/option.h     |  49 ++--
 qemu-img.c                |  61 +++--
 util/qemu-option.c        | 555 ++++++++++++++++++++--------------------------
 22 files changed, 791 insertions(+), 912 deletions(-)

-- 
1.7.11.7

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH V13 1/6] add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print
  2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
@ 2013-04-10  6:25 ` Dong Xu Wang
  2013-05-06 12:16   ` Markus Armbruster
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 2/6] avoid duplication of default value in QemuOpts Dong Xu Wang
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Dong Xu Wang @ 2013-04-10  6:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, Dong Xu Wang, wdongxu, armbru, stefanha

qemu_opts_print has no user now, so can re-write the function safely.

qemu_opts_print will be used while using "qemu-img create", it will
produce the same output as previous code.

The behavior of this function has changed:

1. Print every possible option, whether a value has been set or not.
2. Option descriptors may provide a default value.
3. Print to stdout instead of stderr.

Previously the behavior was to print every option that has been set.
Options that have not been set would be skipped.

Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
---
v12->v13
1) re-write commit message.

v11->v12
1) make def_value_str become the real default value string in opt_set
function.

v10->v11:
1) print all values that have actually been assigned while accept-any
cases.

v7->v8:
1) print "elements => accept any params" while opts_accepts_any() ==
true.
2) since def_print_str is the default value if an option isn't set,
so rename it to def_value_str.


 include/qemu/option.h |  3 ++-
 util/qemu-option.c    | 33 +++++++++++++++++++++++++++------
 2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index bdb6d21..b928ab0 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -96,6 +96,7 @@ typedef struct QemuOptDesc {
     const char *name;
     enum QemuOptType type;
     const char *help;
+    const char *def_value_str;
 } QemuOptDesc;
 
 struct QemuOptsList {
@@ -152,7 +153,7 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
 void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp);
 
 typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
-int qemu_opts_print(QemuOpts *opts, void *dummy);
+int qemu_opts_print(QemuOpts *opts);
 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
                       int abort_on_failure);
 
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 8b74bf1..57cdd57 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -646,6 +646,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
     }
     opt->desc = desc;
     opt->str = g_strdup(value);
+    opt->str = g_strdup(value ?: desc->def_value_str);
     qemu_opt_parse(opt, &local_err);
     if (error_is_set(&local_err)) {
         error_propagate(errp, local_err);
@@ -860,16 +861,36 @@ void qemu_opts_del(QemuOpts *opts)
     g_free(opts);
 }
 
-int qemu_opts_print(QemuOpts *opts, void *dummy)
+int qemu_opts_print(QemuOpts *opts)
 {
     QemuOpt *opt;
+    QemuOptDesc *desc = opts->list->desc;
 
-    fprintf(stderr, "%s: %s:", opts->list->name,
-            opts->id ? opts->id : "<noid>");
-    QTAILQ_FOREACH(opt, &opts->head, next) {
-        fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
+    if (desc[0].name == NULL) {
+        QTAILQ_FOREACH(opt, &opts->head, next) {
+            printf("%s=\"%s\" ", opt->name, opt->str);
+        }
+        return 0;
+    }
+    for (; desc && desc->name; desc++) {
+        const char *value = desc->def_value_str;
+        QemuOpt *opt;
+
+        opt = qemu_opt_find(opts, desc->name);
+        if (opt) {
+            value = opt->str;
+        }
+
+        if (!value) {
+            continue;
+        }
+
+        if (desc->type == QEMU_OPT_STRING) {
+            printf("%s='%s' ", desc->name, value);
+        } else {
+            printf("%s=%s ", desc->name, value);
+        }
     }
-    fprintf(stderr, "\n");
     return 0;
 }
 
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH V13 2/6] avoid duplication of default value in QemuOpts
  2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 1/6] add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print Dong Xu Wang
@ 2013-04-10  6:25 ` Dong Xu Wang
  2013-05-06 11:54   ` Markus Armbruster
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 3/6] Create four QemuOptsList related functions Dong Xu Wang
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Dong Xu Wang @ 2013-04-10  6:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, Dong Xu Wang, wdongxu, armbru, stefanha

According Markus's comments, his patch will move the default value entirely
to QemuOptDesc.

When getting the value of an option that hasn't been set, and
QemuOptDesc has a default value, return that.  Else, behave as
before.

Example: qemu_opt_get_number(opts, "foo", 42)

   If "foo" has been set in opts, return its value.

   Else, if opt's QemuOptDesc has a default value for "foo", return
   that.

   Else, return 42.

   Note that the last argument is useless when QemuOptDesc has a
   default value.  Ugly.  If it bothers us, assert that the argument
   equals the default from QemuOptDesc.

Example: qemu_opt_get(opts, "bar")

   If "bar" has been set in opts, return its value.

   Else, if opt's QemuOptDesc has a default value for "bar", return
   that.

   Else, return NULL.

Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
---
 util/qemu-option.c | 58 +++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/util/qemu-option.c b/util/qemu-option.c
index 57cdd57..4f94000 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -525,10 +525,28 @@ static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
     return NULL;
 }
 
+static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
+                                            const char *name)
+{
+    int i;
+
+    for (i = 0; desc[i].name != NULL; i++) {
+        if (strcmp(desc[i].name, name) == 0) {
+            return &desc[i];
+        }
+    }
+
+    return NULL;
+}
+
 const char *qemu_opt_get(QemuOpts *opts, const char *name)
 {
     QemuOpt *opt = qemu_opt_find(opts, name);
-    return opt ? opt->str : NULL;
+    const QemuOptDesc *desc;
+    desc = find_desc_by_name(opts->list->desc, name);
+
+    return opt ? opt->str :
+        (desc && desc->def_value_str ? desc->def_value_str : NULL);
 }
 
 bool qemu_opt_has_help_opt(QemuOpts *opts)
@@ -546,9 +564,15 @@ bool qemu_opt_has_help_opt(QemuOpts *opts)
 bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
 {
     QemuOpt *opt = qemu_opt_find(opts, name);
+    const QemuOptDesc *desc;
 
-    if (opt == NULL)
+    if (opt == NULL) {
+        desc = find_desc_by_name(opts->list->desc, name);
+        if (desc && desc->def_value_str) {
+            parse_option_bool(name, desc->def_value_str, &defval, NULL);
+        }
         return defval;
+    }
     assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
     return opt->value.boolean;
 }
@@ -556,9 +580,15 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
 {
     QemuOpt *opt = qemu_opt_find(opts, name);
+    const QemuOptDesc *desc;
 
-    if (opt == NULL)
+    if (opt == NULL) {
+        desc = find_desc_by_name(opts->list->desc, name);
+        if (desc && desc->def_value_str) {
+            parse_option_number(name, desc->def_value_str, &defval, NULL);
+        }
         return defval;
+    }
     assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
     return opt->value.uint;
 }
@@ -566,9 +596,15 @@ uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
 {
     QemuOpt *opt = qemu_opt_find(opts, name);
+    const QemuOptDesc *desc;
 
-    if (opt == NULL)
+    if (opt == NULL) {
+        desc = find_desc_by_name(opts->list->desc, name);
+        if (desc && desc->def_value_str) {
+            parse_option_size(name, desc->def_value_str, &defval, NULL);
+        }
         return defval;
+    }
     assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
     return opt->value.uint;
 }
@@ -609,20 +645,6 @@ static bool opts_accepts_any(const QemuOpts *opts)
     return opts->list->desc[0].name == NULL;
 }
 
-static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
-                                            const char *name)
-{
-    int i;
-
-    for (i = 0; desc[i].name != NULL; i++) {
-        if (strcmp(desc[i].name, name) == 0) {
-            return &desc[i];
-        }
-    }
-
-    return NULL;
-}
-
 static void opt_set(QemuOpts *opts, const char *name, const char *value,
                     bool prepend, Error **errp)
 {
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH V13 3/6] Create four QemuOptsList related functions
  2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 1/6] add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print Dong Xu Wang
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 2/6] avoid duplication of default value in QemuOpts Dong Xu Wang
@ 2013-04-10  6:25 ` Dong Xu Wang
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons Dong Xu Wang
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 16+ messages in thread
From: Dong Xu Wang @ 2013-04-10  6:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, Dong Xu Wang, wdongxu, armbru, stefanha

This patch will create 4 functions, count_opts_list, qemu_opts_append,
qemu_opts_free and qemu_opts_print_help, they will be used in following
commits.

Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
---
v12->v13:
1) simply assert that neither argument has merge_lists set.
2) drop superfluous paranthesesis around p == first.

v11->v12:
1) renmae functions.
2) fix loop styles and code styles.
3) qemu_opts_apend will not return NULL now.
4) merge_lists value is from arguments in qemu_opts_append.

v6->v7:
1) Fix typo.

v5->v6:
1) allocate enough space in append_opts_list function.

 include/qemu/option.h |  3 ++
 util/qemu-option.c    | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index b928ab0..c7a5c14 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -157,4 +157,7 @@ int qemu_opts_print(QemuOpts *opts);
 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
                       int abort_on_failure);
 
+QemuOptsList *qemu_opts_append(QemuOptsList *first, QemuOptsList *second);
+void qemu_opts_free(QemuOptsList *list);
+void qemu_opts_print_help(QemuOptsList *list);
 #endif
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 4f94000..0488c27 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -1209,3 +1209,85 @@ int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
     loc_pop(&loc);
     return rc;
 }
+
+static size_t count_opts_list(QemuOptsList *list)
+{
+    size_t i = 0;
+
+    for (i = 0; list && list->desc[i].name; i++) {
+        ;
+    }
+
+    return i;
+}
+
+/* Create a new QemuOptsList and make its desc to the merge of first
+ * and second. It will allocate space for one new QemuOptsList plus
+ * enough space for QemuOptDesc in first and second QemuOptsList.
+ * First argument's QemuOptDesc members take precedence over second's.
+ * The result's name and implied_opt_name are not copied from them.
+ * Both merge_lists should not be set. Both list can be NULL.
+ */
+QemuOptsList *qemu_opts_append(QemuOptsList *first,
+                               QemuOptsList *second)
+{
+    size_t num_first_opts, num_second_opts;
+    QemuOptsList *dest = NULL;
+    int i = 0;
+    int index = 0;
+    QemuOptsList *p = first;
+
+    num_first_opts = count_opts_list(first);
+    num_second_opts = count_opts_list(second);
+
+    dest = g_malloc0(sizeof(QemuOptsList)
+        + (num_first_opts + num_second_opts + 1) * sizeof(QemuOptDesc));
+
+    dest->name = "append_opts_list";
+    dest->implied_opt_name = NULL;
+    assert((!first || !first->merge_lists)
+        && (!second || !second->merge_lists));
+    QTAILQ_INIT(&dest->head);
+
+    for (i = 0; p && p->desc[i].name; i++) {
+        if (!find_desc_by_name(dest->desc, p->desc[i].name)) {
+            dest->desc[index].name = g_strdup(p->desc[i].name);
+            dest->desc[index].help = g_strdup(p->desc[i].help);
+            dest->desc[index].type = p->desc[i].type;
+            dest->desc[index].def_value_str =
+                g_strdup(p->desc[i].def_value_str);
+            index++;
+        }
+        if (p == first && p && !p->desc[i].name) {
+            p = second;
+            i = 0;
+        }
+    }
+    dest->desc[index].name = NULL;
+    return dest;
+}
+
+/* free a QemuOptsList, can accept NULL as arguments */
+void qemu_opts_free(QemuOptsList *list)
+{
+    int i = 0;
+
+    for (i = 0; list && list->desc[i].name; i++) {
+        g_free((char *)list->desc[i].name);
+        g_free((char *)list->desc[i].help);
+        g_free((char *)list->desc[i].def_value_str);
+    }
+
+    g_free(list);
+}
+
+void qemu_opts_print_help(QemuOptsList *list)
+{
+    int i = 0;
+    printf("Supported options:\n");
+    for (i = 0; list && list->desc[i].name; i++) {
+        printf("%-16s %s\n", list->desc[i].name,
+            list->desc[i].help ?
+                list->desc[i].help : "No description available");
+    }
+}
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons
  2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
                   ` (2 preceding siblings ...)
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 3/6] Create four QemuOptsList related functions Dong Xu Wang
@ 2013-04-10  6:25 ` Dong Xu Wang
  2013-05-06 12:20   ` Markus Armbruster
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 5/6] Use QemuOpts support in block layer Dong Xu Wang
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Dong Xu Wang @ 2013-04-10  6:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, Dong Xu Wang, wdongxu, armbru, stefanha

These functions will be used in next commit. qemu_opt_get_(*)_del functions
are used to make sure we have the same behaviors as before: after get an
option value, options++.

Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
---
 include/qemu/option.h |  11 +++++-
 util/qemu-option.c    | 103 ++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 105 insertions(+), 9 deletions(-)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index c7a5c14..d63e447 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -108,6 +108,7 @@ struct QemuOptsList {
 };
 
 const char *qemu_opt_get(QemuOpts *opts, const char *name);
+const char *qemu_opt_get_del(QemuOpts *opts, const char *name);
 /**
  * qemu_opt_has_help_opt:
  * @opts: options to search for a help request
@@ -121,13 +122,18 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name);
  */
 bool qemu_opt_has_help_opt(QemuOpts *opts);
 bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
+bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
+uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
+                               uint64_t defval);
 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
+int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value);
 void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
                       Error **errp);
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
 int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val);
+int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val);
 typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                      int abort_on_failure);
@@ -144,7 +150,10 @@ const char *qemu_opts_id(QemuOpts *opts);
 void qemu_opts_del(QemuOpts *opts);
 void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
-QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
+int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
+                               const char *firstname);
+QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
+                          int permit_abbrev);
 void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
                             int permit_abbrev);
 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 0488c27..5db6d76 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -33,6 +33,8 @@
 #include "qapi/qmp/qerror.h"
 #include "qemu/option_int.h"
 
+static void qemu_opt_del(QemuOpt *opt);
+
 /*
  * Extracts the name of an option from the parameter string (p points at the
  * first byte of the option name)
@@ -549,6 +551,16 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
         (desc && desc->def_value_str ? desc->def_value_str : NULL);
 }
 
+const char *qemu_opt_get_del(QemuOpts *opts, const char *name)
+{
+    QemuOpt *opt = qemu_opt_find(opts, name);
+    const char *str = opt ? g_strdup(opt->str) : NULL;
+    if (opt) {
+        qemu_opt_del(opt);
+    }
+    return str;
+}
+
 bool qemu_opt_has_help_opt(QemuOpts *opts)
 {
     QemuOpt *opt;
@@ -577,6 +589,22 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
     return opt->value.boolean;
 }
 
+bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
+{
+    QemuOpt *opt = qemu_opt_find(opts, name);
+    bool ret;
+
+    if (opt == NULL) {
+        return defval;
+    }
+    ret = opt->value.boolean;
+    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
+    if (opt) {
+        qemu_opt_del(opt);
+    }
+    return ret;
+}
+
 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
 {
     QemuOpt *opt = qemu_opt_find(opts, name);
@@ -609,6 +637,23 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
     return opt->value.uint;
 }
 
+uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
+                               uint64_t defval)
+{
+    QemuOpt *opt = qemu_opt_find(opts, name);
+    uint64_t ret;
+
+    if (opt == NULL) {
+        return defval;
+    }
+    ret = opt->value.uint;
+    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
+    if (opt) {
+        qemu_opt_del(opt);
+    }
+    return ret;
+}
+
 static void qemu_opt_parse(QemuOpt *opt, Error **errp)
 {
     if (opt->desc == NULL)
@@ -646,7 +691,7 @@ static bool opts_accepts_any(const QemuOpts *opts)
 }
 
 static void opt_set(QemuOpts *opts, const char *name, const char *value,
-                    bool prepend, Error **errp)
+                    bool prepend, bool replace, Error **errp)
 {
     QemuOpt *opt;
     const QemuOptDesc *desc;
@@ -658,6 +703,11 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
         return;
     }
 
+    opt = qemu_opt_find(opts, name);
+    if (replace && opt) {
+        qemu_opt_del(opt);
+    }
+
     opt = g_malloc0(sizeof(*opt));
     opt->name = g_strdup(name);
     opt->opts = opts;
@@ -667,7 +717,6 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
         QTAILQ_INSERT_TAIL(&opts->head, opt, next);
     }
     opt->desc = desc;
-    opt->str = g_strdup(value);
     opt->str = g_strdup(value ?: desc->def_value_str);
     qemu_opt_parse(opt, &local_err);
     if (error_is_set(&local_err)) {
@@ -680,7 +729,29 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
 {
     Error *local_err = NULL;
 
-    opt_set(opts, name, value, false, &local_err);
+    opt_set(opts, name, value, false, false, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * If name exists, the function will delete the opt first and then add a new
+ * one.
+ */
+int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value)
+{
+    Error *local_err = NULL;
+    QemuOpt *opt = qemu_opt_find(opts, name);
+
+    if (opt) {
+        qemu_opt_del(opt);
+    }
+    opt_set(opts, name, value, false, true, &local_err);
     if (error_is_set(&local_err)) {
         qerror_report_err(local_err);
         error_free(local_err);
@@ -693,7 +764,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
 void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
                       Error **errp)
 {
-    opt_set(opts, name, value, false, errp);
+    opt_set(opts, name, value, false, false, errp);
 }
 
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
@@ -740,6 +811,16 @@ int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val)
     return 0;
 }
 
+int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val)
+{
+    QemuOpt *opt = qemu_opt_find(opts, name);
+
+    if (opt) {
+        qemu_opt_del(opt);
+    }
+    return qemu_opt_set_number(opts, name, val);
+}
+
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                      int abort_on_failure)
 {
@@ -917,7 +998,7 @@ int qemu_opts_print(QemuOpts *opts)
 }
 
 static int opts_do_parse(QemuOpts *opts, const char *params,
-                         const char *firstname, bool prepend)
+                         const char *firstname, bool prepend, bool replace)
 {
     char option[128], value[1024];
     const char *p,*pe,*pc;
@@ -953,7 +1034,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
         }
         if (strcmp(option, "id") != 0) {
             /* store and parse */
-            opt_set(opts, option, value, prepend, &local_err);
+            opt_set(opts, option, value, prepend, replace, &local_err);
             if (error_is_set(&local_err)) {
                 qerror_report_err(local_err);
                 error_free(local_err);
@@ -969,7 +1050,13 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
 
 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
 {
-    return opts_do_parse(opts, params, firstname, false);
+    return opts_do_parse(opts, params, firstname, false, false);
+}
+
+int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
+                               const char *firstname)
+{
+    return opts_do_parse(opts, params, firstname, false, true);
 }
 
 static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
@@ -1008,7 +1095,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
         return NULL;
     }
 
-    if (opts_do_parse(opts, params, firstname, defaults) != 0) {
+    if (opts_do_parse(opts, params, firstname, defaults, false) != 0) {
         qemu_opts_del(opts);
         return NULL;
     }
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH V13 5/6] Use QemuOpts support in block layer
  2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
                   ` (3 preceding siblings ...)
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons Dong Xu Wang
@ 2013-04-10  6:25 ` Dong Xu Wang
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 6/6] remove QEMUOptionParameter related functions and struct Dong Xu Wang
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 16+ messages in thread
From: Dong Xu Wang @ 2013-04-10  6:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, Dong Xu Wang, wdongxu, armbru, stefanha

This patch will use QemuOpts related functions in block layer, add
a member bdrv_create_opts 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.

Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
---
v12->v13:
1) split into 2 patches. one for block, one for QemuOpts funcitons.
2) fix leaking cco->opts.
3) other small fix.

v11->v12:
1) create functions, such as qemu_opt_get_del and qemu_opt_replace_set.
These functions works like origin code.
2) use QEMU_OPT_SIZE, not QEMU_OPT_NUMBER.
3) in bdrv_create, if opts is NULL, will create an empty one, so can
discard if(opts) code safely.

v10->v11:
1) qed.h move QED_DEFAULT_CLUSTER_SIZE from enum to macro, or
qemu_opts_print produce un-expanded cluster_size.
2) In qcow2.c and qcow.c, bdrv_create_file(filename, NULL), NULL ->
opts,
or while using protocol, there will be an error.

v8->v9:
1) add qemu_ prefix to gluster_create_opts.
2) fix bug: bdrv_gluster_unix and bdrv_gluster_rdma should also be
converted.

v7->v8:
1) rebase to upstream source tree.
2) add gluster.c, raw-win32.c, and rbd.c.

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.

 block.c                   |  98 ++++++++++++--------------
 block/cow.c               |  46 ++++++------
 block/gluster.c           |  37 +++++-----
 block/iscsi.c             |  35 +++++-----
 block/qcow.c              |  61 ++++++++--------
 block/qcow2.c             | 173 +++++++++++++++++++++++-----------------------
 block/qed.c               |  86 +++++++++++------------
 block/qed.h               |   2 +-
 block/raw-posix.c         |  59 +++++++---------
 block/raw-win32.c         |  31 +++++----
 block/raw.c               |  30 ++++----
 block/rbd.c               |  62 ++++++++---------
 block/sheepdog.c          |  79 ++++++++++-----------
 block/vdi.c               |  70 +++++++++----------
 block/vmdk.c              |  90 ++++++++++++------------
 block/vpc.c               |  57 +++++++--------
 block/vvfat.c             |  11 +--
 include/block/block.h     |   5 +-
 include/block/block_int.h |   6 +-
 qemu-img.c                |  61 ++++++++--------
 20 files changed, 535 insertions(+), 564 deletions(-)

diff --git a/block.c b/block.c
index 602d8a4..45e1d96 100644
--- a/block.c
+++ b/block.c
@@ -355,7 +355,7 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name)
 typedef struct CreateCo {
     BlockDriver *drv;
     char *filename;
-    QEMUOptionParameter *options;
+    QemuOpts *opts;
     int ret;
 } CreateCo;
 
@@ -364,11 +364,10 @@ 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)
+int bdrv_create(BlockDriver *drv, const char* filename, QemuOpts *opts)
 {
     int ret;
 
@@ -376,7 +375,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
     CreateCo cco = {
         .drv = drv,
         .filename = g_strdup(filename),
-        .options = options,
+        .opts = opts ?: qemu_opts_create_nofail(drv->bdrv_create_opts),
         .ret = NOT_DONE,
     };
 
@@ -399,11 +398,14 @@ int bdrv_create(BlockDriver *drv, const char* filename,
     ret = cco.ret;
 
 out:
+    if (!opts) {
+        qemu_opts_del(cco.opts);
+    }
     g_free(cco.filename);
     return ret;
 }
 
-int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
+int bdrv_create_file(const char *filename, QemuOpts *opts)
 {
     BlockDriver *drv;
 
@@ -412,7 +414,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
         return -ENOENT;
     }
 
-    return bdrv_create(drv, filename, options);
+    return bdrv_create(drv, filename, opts);
 }
 
 /*
@@ -924,7 +926,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         BlockDriverState *bs1;
         int64_t total_size;
         BlockDriver *bdrv_qcow2;
-        QEMUOptionParameter *create_options;
+        QemuOpts *opts;
         char backing_filename[PATH_MAX];
 
         if (qdict_size(options) != 0) {
@@ -963,19 +965,16 @@ 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);
+        opts = qemu_opts_create_nofail(bdrv_qcow2->bdrv_create_opts);
 
-        set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
-        set_option_parameter(create_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(create_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, create_options);
-        free_option_parameters(create_options);
+        ret = bdrv_create(bdrv_qcow2, tmp_filename, opts);
+        qemu_opts_del(opts);
         if (ret < 0) {
             goto fail;
         }
@@ -4640,8 +4639,10 @@ void bdrv_img_create(const char *filename, const char *fmt,
                      char *options, uint64_t img_size, int flags,
                      Error **errp, bool quiet)
 {
-    QEMUOptionParameter *param = NULL, *create_options = NULL;
-    QEMUOptionParameter *backing_fmt, *backing_file, *size;
+    QemuOpts *opts = NULL;
+    QemuOptsList *create_opts = NULL;
+    const char *backing_fmt, *backing_file;
+    int64_t size;
     BlockDriverState *bs = NULL;
     BlockDriver *drv, *proto_drv;
     BlockDriver *backing_drv = NULL;
@@ -4659,28 +4660,23 @@ void bdrv_img_create(const char *filename, const char *fmt,
         error_setg(errp, "Unknown protocol '%s'", filename);
         return;
     }
-
-    create_options = append_option_parameters(create_options,
-                                              drv->create_options);
-    create_options = append_option_parameters(create_options,
-                                              proto_drv->create_options);
-
+    create_opts = qemu_opts_append(drv->bdrv_create_opts,
+                                   proto_drv->bdrv_create_opts);
     /* Create parameter list with default values */
-    param = parse_option_parameters("", create_options, param);
+    opts = qemu_opts_create_nofail(create_opts);
 
-    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_replace(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,
+        if (qemu_opt_replace_set(opts, BLOCK_OPT_BACKING_FILE,
                                  base_filename)) {
             error_setg(errp, "Backing file not supported for file format '%s'",
                        fmt);
@@ -4689,39 +4685,37 @@ void 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_replace_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)) {
+    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);
+    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->value.s);
+            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 = get_option_parameter(param, BLOCK_OPT_SIZE);
-    if (size && size->value.n == -1) {
-        if (backing_file && backing_file->value.s) {
+    size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
+    if (size == -1) {
+        if (backing_file) {
             uint64_t size;
-            char buf[32];
             int back_flags;
 
             /* backing files always opened read-only */
@@ -4730,18 +4724,16 @@ void bdrv_img_create(const char *filename, const char *fmt,
 
             bs = bdrv_new("");
 
-            ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags,
-                            backing_drv);
+            ret = bdrv_open(bs, backing_file, NULL, back_flags, backing_drv);
             if (ret < 0) {
                 error_setg_errno(errp, -ret, "Could not open '%s'",
-                                 backing_file->value.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_replace_set_number(opts, BLOCK_OPT_SIZE, size);
         } else {
             error_setg(errp, "Image creation needs a size parameter");
             goto out;
@@ -4750,10 +4742,10 @@ void bdrv_img_create(const char *filename, const char *fmt,
 
     if (!quiet) {
         printf("Formatting '%s', fmt=%s ", filename, fmt);
-        print_option_parameters(param);
+        qemu_opts_print(opts);
         puts("");
     }
-    ret = bdrv_create(drv, filename, param);
+    ret = bdrv_create(drv, filename, opts);
     if (ret < 0) {
         if (ret == -ENOTSUP) {
             error_setg(errp,"Formatting or formatting option not supported for "
@@ -4768,8 +4760,10 @@ void bdrv_img_create(const char *filename, const char *fmt,
     }
 
 out:
-    free_option_parameters(create_options);
-    free_option_parameters(param);
+    qemu_opts_free(create_opts);
+    if (opts) {
+        qemu_opts_del(opts);
+    }
 
     if (bs) {
         bdrv_delete(bs);
diff --git a/block/cow.c b/block/cow.c
index 9f94599..3f50e0e 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,11 @@ 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 */
+    image_sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
+    image_filename = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
 
-    ret = bdrv_create_file(filename, options);
+    ret = bdrv_create_file(filename, opts);
     if (ret < 0) {
         return ret;
     }
@@ -318,18 +312,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_SIZE,
+            .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 +343,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_opts       = &cow_create_opts,
 };
 
 static void bdrv_cow_init(void)
diff --git a/block/gluster.c b/block/gluster.c
index 9ccd4d4..39339f2 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -335,8 +335,7 @@ out:
     return ret;
 }
 
-static int qemu_gluster_create(const char *filename,
-        QEMUOptionParameter *options)
+static int qemu_gluster_create(const char *filename, QemuOpts *opts)
 {
     struct glfs *glfs;
     struct glfs_fd *fd;
@@ -350,12 +349,8 @@ static int qemu_gluster_create(const char *filename,
         goto out;
     }
 
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            total_size = options->value.n / BDRV_SECTOR_SIZE;
-        }
-        options++;
-    }
+    total_size =
+        qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
 
     fd = glfs_creat(glfs, gconf->image,
         O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
@@ -544,13 +539,17 @@ static void qemu_gluster_close(BlockDriverState *bs)
     glfs_fini(s->glfs);
 }
 
-static QEMUOptionParameter qemu_gluster_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    { NULL }
+static QemuOptsList qemu_gluster_create_opts = {
+    .name = "qemu-gluster-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_gluster_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "Virtual disk size"
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_gluster = {
@@ -565,7 +564,7 @@ static BlockDriver bdrv_gluster = {
     .bdrv_aio_readv               = qemu_gluster_aio_readv,
     .bdrv_aio_writev              = qemu_gluster_aio_writev,
     .bdrv_aio_flush               = qemu_gluster_aio_flush,
-    .create_options               = qemu_gluster_create_options,
+    .bdrv_create_opts             = &qemu_gluster_create_opts,
 };
 
 static BlockDriver bdrv_gluster_tcp = {
@@ -580,7 +579,7 @@ static BlockDriver bdrv_gluster_tcp = {
     .bdrv_aio_readv               = qemu_gluster_aio_readv,
     .bdrv_aio_writev              = qemu_gluster_aio_writev,
     .bdrv_aio_flush               = qemu_gluster_aio_flush,
-    .create_options               = qemu_gluster_create_options,
+    .bdrv_create_opts             = &qemu_gluster_create_opts,
 };
 
 static BlockDriver bdrv_gluster_unix = {
@@ -595,7 +594,7 @@ static BlockDriver bdrv_gluster_unix = {
     .bdrv_aio_readv               = qemu_gluster_aio_readv,
     .bdrv_aio_writev              = qemu_gluster_aio_writev,
     .bdrv_aio_flush               = qemu_gluster_aio_flush,
-    .create_options               = qemu_gluster_create_options,
+    .bdrv_create_opts             = &qemu_gluster_create_opts,
 };
 
 static BlockDriver bdrv_gluster_rdma = {
@@ -610,7 +609,7 @@ static BlockDriver bdrv_gluster_rdma = {
     .bdrv_aio_readv               = qemu_gluster_aio_readv,
     .bdrv_aio_writev              = qemu_gluster_aio_writev,
     .bdrv_aio_flush               = qemu_gluster_aio_flush,
-    .create_options               = qemu_gluster_create_options,
+    .bdrv_create_opts             = &qemu_gluster_create_opts,
 };
 
 static void bdrv_gluster_init(void)
diff --git a/block/iscsi.c b/block/iscsi.c
index 92d6eae..496e39f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -904,9 +904,7 @@ static char *parse_initiator_name(const char *target)
         if (!opts) {
             opts = QTAILQ_FIRST(&list->head);
         }
-        if (opts) {
-            name = qemu_opt_get(opts, "initiator-name");
-        }
+        name = qemu_opt_get(opts, "initiator-name");
     }
 
     if (name) {
@@ -1184,7 +1182,7 @@ static int iscsi_has_zero_init(BlockDriverState *bs)
     return 0;
 }
 
-static int iscsi_create(const char *filename, QEMUOptionParameter *options)
+static int iscsi_create(const char *filename,  QemuOpts *opts)
 {
     int ret = 0;
     int64_t total_size = 0;
@@ -1194,13 +1192,8 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options)
     memset(&bs, 0, sizeof(BlockDriverState));
 
     /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, "size")) {
-            total_size = options->value.n / BDRV_SECTOR_SIZE;
-        }
-        options++;
-    }
-
+    total_size =
+        qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
     bs.opaque = g_malloc0(sizeof(struct IscsiLun));
     iscsilun = bs.opaque;
 
@@ -1229,13 +1222,17 @@ out:
     return ret;
 }
 
-static QEMUOptionParameter iscsi_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    { NULL }
+static QemuOptsList iscsi_create_opts = {
+    .name = "iscsi-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(iscsi_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "Virtual disk size"
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_iscsi = {
@@ -1246,7 +1243,7 @@ static BlockDriver bdrv_iscsi = {
     .bdrv_file_open  = iscsi_open,
     .bdrv_close      = iscsi_close,
     .bdrv_create     = iscsi_create,
-    .create_options  = iscsi_create_options,
+    .bdrv_create_opts = &iscsi_create_opts,
 
     .bdrv_getlength  = iscsi_getlength,
     .bdrv_truncate   = iscsi_truncate,
diff --git a/block/qcow.c b/block/qcow.c
index 13d396b..c3701bd 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,14 @@ 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;
-        }
-        options++;
+    /* Read out opts */
+    total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
+    backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
+    if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, 0)) {
+        flags |= BLOCK_FLAG_ENCRYPT;
     }
 
-    ret = bdrv_create_file(filename, options);
+    ret = bdrv_create_file(filename, opts);
     if (ret < 0) {
         return ret;
     }
@@ -851,24 +846,28 @@ 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_SIZE,
+            .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",
+            .def_value_str = "off"
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_qcow = {
@@ -889,7 +888,7 @@ static BlockDriver bdrv_qcow = {
     .bdrv_write_compressed  = qcow_write_compressed,
     .bdrv_get_info          = qcow_get_info,
 
-    .create_options = qcow_create_options,
+    .bdrv_create_opts       = &qcow_create_opts,
 };
 
 static void bdrv_qcow_init(void)
diff --git a/block/qcow2.c b/block/qcow2.c
index 7e7d775..5871192 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1224,7 +1224,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)
+                         QemuOpts *opts, int version)
 {
     /* Calculate cluster_bits */
     int cluster_bits;
@@ -1255,7 +1255,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, opts);
     if (ret < 0) {
         return ret;
     }
@@ -1358,7 +1358,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;
@@ -1367,45 +1367,41 @@ 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;
-        }
-        options++;
+    sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
+    backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
+    backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);
+    if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, 0)) {
+        flags |= BLOCK_FLAG_ENCRYPT;
+    }
+    cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
+                                         DEFAULT_CLUSTER_SIZE);
+    buf = qemu_opt_get_del(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_del(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_del(opts, BLOCK_OPT_LAZY_REFCOUNTS, 0)) {
+        flags |= BLOCK_FLAG_LAZY_REFCOUNTS;
     }
 
     if (backing_file && prealloc) {
@@ -1421,7 +1417,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, opts, version);
 }
 
 static int qcow2_make_empty(BlockDriverState *bs)
@@ -1682,49 +1678,55 @@ 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_SIZE,
+            .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",
+            .def_value_str = "off"
+        },
+        {
+            .name = BLOCK_OPT_CLUSTER_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "qcow2 cluster size",
+            .def_value_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",
+            .def_value_str = "off"
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_qcow2 = {
@@ -1762,8 +1764,9 @@ static BlockDriver bdrv_qcow2 = {
 
     .bdrv_invalidate_cache      = qcow2_invalidate_cache,
 
-    .create_options = qcow2_create_options,
     .bdrv_check = qcow2_check,
+
+    .bdrv_create_opts     = &qcow2_create_opts,
 };
 
 static void bdrv_qcow2_init(void)
diff --git a/block/qed.c b/block/qed.c
index 4651403..acffc2d 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,24 +611,14 @@ 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++;
-    }
+    image_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
+    backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
+    backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);
+    cluster_size = qemu_opt_get_size_del(opts,
+                                         BLOCK_OPT_CLUSTER_SIZE,
+                                         QED_DEFAULT_CLUSTER_SIZE);
+    table_size = qemu_opt_get_size_del(opts, BLOCK_OPT_TABLE_SIZE,
+                                       QED_DEFAULT_TABLE_SIZE);
 
     if (!qed_is_cluster_size_valid(cluster_size)) {
         fprintf(stderr, "QED cluster size must be within range [%u, %u] and power of 2\n",
@@ -1537,36 +1527,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_SIZE,
+            .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_value_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_opts         = &qed_create_opts,
 
     .bdrv_probe               = bdrv_qed_probe,
     .bdrv_rebind              = bdrv_qed_rebind,
diff --git a/block/qed.h b/block/qed.h
index 2b4dded..99a7726 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -43,6 +43,7 @@
  *
  * All fields are little-endian on disk.
  */
+#define  QED_DEFAULT_CLUSTER_SIZE  65536
 
 enum {
     QED_MAGIC = 'Q' | 'E' << 8 | 'D' << 16 | '\0' << 24,
@@ -69,7 +70,6 @@ enum {
      */
     QED_MIN_CLUSTER_SIZE = 4 * 1024, /* in bytes */
     QED_MAX_CLUSTER_SIZE = 64 * 1024 * 1024,
-    QED_DEFAULT_CLUSTER_SIZE = 64 * 1024,
 
     /* Allocated clusters are tracked using a 2-level pagetable.  Table size is
      * a multiple of clusters so large maximum image sizes can be supported
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 99ac869..12b23d4 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -123,6 +123,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;
@@ -1009,19 +1022,14 @@ 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++;
-    }
+    total_size =
+        qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
 
     fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                    0644);
@@ -1148,15 +1156,6 @@ static coroutine_fn BlockDriverAIOCB *raw_aio_discard(BlockDriverState *bs,
                        cb, opaque, QEMU_AIO_DISCARD);
 }
 
-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",
@@ -1179,8 +1178,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_opts   = &file_proto_create_opts,
 };
 
 /***********************************************/
@@ -1465,20 +1463,15 @@ static coroutine_fn BlockDriverAIOCB *hdev_aio_discard(BlockDriverState *bs,
                        cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
 }
 
-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++;
-    }
+    total_size =
+        qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
 
     fd = qemu_open(filename, O_WRONLY | O_BINARY);
     if (fd < 0)
@@ -1502,7 +1495,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,
@@ -1511,7 +1504,6 @@ 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,
@@ -1520,9 +1512,10 @@ static BlockDriver bdrv_host_device = {
     .bdrv_aio_discard   = hdev_aio_discard,
 
     .bdrv_truncate      = raw_truncate,
-    .bdrv_getlength	= raw_getlength,
+    .bdrv_getlength     = raw_getlength,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
+    .bdrv_create_opts   = &file_proto_create_opts,
 
     /* generic scsi device */
 #ifdef __linux__
@@ -1637,7 +1630,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,
@@ -1653,6 +1645,7 @@ static BlockDriver bdrv_host_floppy = {
     .bdrv_is_inserted   = floppy_is_inserted,
     .bdrv_media_changed = floppy_media_changed,
     .bdrv_eject         = floppy_eject,
+    .bdrv_create_opts   = &file_proto_create_opts,
 };
 
 static int cdrom_open(BlockDriverState *bs, const char *filename,
@@ -1740,7 +1733,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,
@@ -1760,6 +1752,8 @@ static BlockDriver bdrv_host_cdrom = {
     /* generic scsi device */
     .bdrv_ioctl         = hdev_ioctl,
     .bdrv_aio_ioctl     = hdev_aio_ioctl,
+
+    .bdrv_create_opts   = &file_proto_create_opts,
 };
 #endif /* __linux__ */
 
@@ -1863,7 +1857,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-win32.c b/block/raw-win32.c
index ece2f1a..525a398 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -385,18 +385,15 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
     return st.st_size;
 }
 
-static int raw_create(const char *filename, QEMUOptionParameter *options)
+static int raw_create(const char *filename, QemuOpts *opts)
 {
     int fd;
     int64_t total_size = 0;
 
     /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            total_size = options->value.n / 512;
-        }
-        options++;
-    }
+
+    total_size =
+        qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
 
     fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                    0644);
@@ -408,13 +405,17 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
     return 0;
 }
 
-static QEMUOptionParameter raw_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    { NULL }
+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_SIZE,
+            .help = "Virtual disk size"
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_file = {
@@ -434,7 +435,7 @@ static BlockDriver bdrv_file = {
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
-    .create_options = raw_create_options,
+    .bdrv_create_opts   = &raw_create_opts,
 };
 
 /***********************************************/
diff --git a/block/raw.c b/block/raw.c
index ce10422..f526ab8 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_SIZE,
+            .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_opts   = &raw_create_opts,
 };
 
 static void bdrv_raw_init(void)
diff --git a/block/rbd.c b/block/rbd.c
index 1a8ea6d..452e488 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -287,7 +287,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
     return ret;
 }
 
-static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options)
+static int qemu_rbd_create(const char *filename, QemuOpts *opts)
 {
     int64_t bytes = 0;
     int64_t objsize;
@@ -310,24 +310,18 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options)
     }
 
     /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            bytes = options->value.n;
-        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
-            if (options->value.n) {
-                objsize = options->value.n;
-                if ((objsize - 1) & objsize) {    /* not a power of 2? */
-                    error_report("obj size needs to be power of 2");
-                    return -EINVAL;
-                }
-                if (objsize < 4096) {
-                    error_report("obj size too small");
-                    return -EINVAL;
-                }
-                obj_order = ffs(objsize) - 1;
-            }
+    bytes = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
+    objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0);
+    if (objsize) {
+        if ((objsize - 1) & objsize) {    /* not a power of 2? */
+            error_report("obj size needs to be power of 2");
+            return -EINVAL;
+        }
+        if (objsize < 4096) {
+            error_report("obj size too small");
+            return -EINVAL;
         }
-        options++;
+        obj_order = ffs(objsize) - 1;
     }
 
     clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
@@ -921,20 +915,24 @@ static BlockDriverAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs,
 }
 #endif
 
-static QEMUOptionParameter qemu_rbd_create_options[] = {
-    {
-     .name = BLOCK_OPT_SIZE,
-     .type = OPT_SIZE,
-     .help = "Virtual disk size"
-    },
-    {
-     .name = BLOCK_OPT_CLUSTER_SIZE,
-     .type = OPT_SIZE,
-     .help = "RBD object size"
-    },
-    {NULL}
+static QemuOptsList rbd_create_opts = {
+    .name = "rbd-create-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(rbd_create_opts.head),
+    .desc = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_CLUSTER_SIZE,
+            .type = QEMU_OPT_SIZE,
+            .help = "RBD object size",
+            .def_value_str = stringify(0),
+        },
+        { /* end of list */ }
+    }
 };
-
 static BlockDriver bdrv_rbd = {
     .format_name        = "rbd",
     .instance_size      = sizeof(BDRVRBDState),
@@ -942,7 +940,7 @@ static BlockDriver bdrv_rbd = {
     .bdrv_close         = qemu_rbd_close,
     .bdrv_create        = qemu_rbd_create,
     .bdrv_get_info      = qemu_rbd_getinfo,
-    .create_options     = qemu_rbd_create_options,
+    .bdrv_create_opts   = &rbd_create_opts,
     .bdrv_getlength     = qemu_rbd_getlength,
     .bdrv_truncate      = qemu_rbd_truncate,
     .protocol_name      = "rbd",
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 987018e..4e46e08 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1305,12 +1305,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;
@@ -1329,26 +1329,18 @@ 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;
-            }
-        }
-        options++;
+    vdi_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
+    backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
+    buf = qemu_opt_get_del(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;
     }
-
     if (vdi_size > SD_MAX_VDI_SIZE) {
         error_report("too big image size");
         ret = -EINVAL;
@@ -2070,24 +2062,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_SIZE,
+            .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 */ }
+    }
 };
 
 static BlockDriver bdrv_sheepdog = {
@@ -2112,7 +2107,7 @@ static BlockDriver bdrv_sheepdog = {
     .bdrv_save_vmstate  = sd_save_vmstate,
     .bdrv_load_vmstate  = sd_load_vmstate,
 
-    .create_options = sd_create_options,
+    .bdrv_create_opts   = &sd_create_opts,
 };
 
 static BlockDriver bdrv_sheepdog_tcp = {
@@ -2137,7 +2132,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
     .bdrv_save_vmstate  = sd_save_vmstate,
     .bdrv_load_vmstate  = sd_load_vmstate,
 
-    .create_options = sd_create_options,
+    .bdrv_create_opts = &sd_create_opts,
 };
 
 static BlockDriver bdrv_sheepdog_unix = {
@@ -2162,7 +2157,7 @@ static BlockDriver bdrv_sheepdog_unix = {
     .bdrv_save_vmstate  = sd_save_vmstate,
     .bdrv_load_vmstate  = sd_load_vmstate,
 
-    .create_options = sd_create_options,
+    .bdrv_create_opts = &sd_create_opts,
 };
 
 static void bdrv_sheepdog_init(void)
diff --git a/block/vdi.c b/block/vdi.c
index 2662d89..0e9d1f8 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -633,7 +633,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;
@@ -648,25 +648,18 @@ 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;
+    bytes = qemu_opt_get_size_del(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_del(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
-        }
-        options++;
+    if (qemu_opt_get_bool_del(opts, BLOCK_OPT_STATIC, 0)) {
+        image_type = VDI_TYPE_STATIC;
     }
+#endif
 
     fd = qemu_open(filename,
                    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
@@ -746,29 +739,34 @@ 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_SIZE,
+            .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_value_str = stringify(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",
+            .def_value_str = "off"
+        },
 #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 = {
@@ -789,7 +787,7 @@ static BlockDriver bdrv_vdi = {
 
     .bdrv_get_info = vdi_get_info,
 
-    .create_options = vdi_create_options,
+    .bdrv_create_opts = &vdi_create_opts,
     .bdrv_check = vdi_check,
 };
 
diff --git a/block/vmdk.c b/block/vmdk.c
index 7bad757..6a83bb9 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1429,7 +1429,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];
@@ -1470,21 +1470,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_ADAPTER_TYPE)) {
-            adapter_type = options->value.s;
-        } 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;
-        }
-        options++;
+    /* Read out opts */
+    total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
+    adapter_type = qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE);
+    backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
+    if (qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, 0)) {
+        flags |= BLOCK_FLAG_COMPAT6;
     }
+    fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
     if (!adapter_type) {
         adapter_type = "ide";
     } else if (strcmp(adapter_type, "ide") &&
@@ -1665,36 +1658,41 @@ 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_ADAPTER_TYPE,
-        .type = OPT_STRING,
-        .help = "Virtual adapter type, can be one of "
-                "ide (default), lsilogic, buslogic or legacyESX"
-    },
-    {
-        .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_SIZE,
+            .help = "Virtual disk size"
+        },
+        {
+            .name = BLOCK_OPT_ADAPTER_TYPE,
+            .type = OPT_STRING,
+            .help = "Virtual adapter type, can be one of "
+                    "ide (default), lsilogic, buslogic or legacyESX"
+        },
+        {
+            .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",
+            .def_value_str = "off"
+        },
+        {
+            .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 = {
@@ -1711,7 +1709,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_opts = &vmdk_create_opts,
 };
 
 static void bdrv_vmdk_init(void)
diff --git a/block/vpc.c b/block/vpc.c
index 3cad52e..02d6fb3 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -683,34 +683,31 @@ 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")) {
+    /* Read out opts */
+    total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
+    disk_type_param = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
+    if (disk_type_param) {
+        if (!strcmp(disk_type_param, "dynamic")) {
             disk_type = VHD_DYNAMIC;
-        } else if (!strcmp(disk_type_param->value.s, "fixed")) {
+        } else if (!strcmp(disk_type_param, "fixed")) {
             disk_type = VHD_FIXED;
         } else {
             return -EINVAL;
         }
-    } else {
-        disk_type = VHD_DYNAMIC;
     }
 
     /* Create the file */
@@ -798,20 +795,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_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} "
+        },
+        { /* end of list */ }
+    }
 };
 
 static BlockDriver bdrv_vpc = {
@@ -827,7 +828,7 @@ static BlockDriver bdrv_vpc = {
     .bdrv_read              = vpc_co_read,
     .bdrv_write             = vpc_co_write,
 
-    .create_options = vpc_create_options,
+    .bdrv_create_opts = &vpc_create_opts,
 };
 
 static void bdrv_vpc_init(void)
diff --git a/block/vvfat.c b/block/vvfat.c
index ef74c30..51d95ed 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2803,7 +2803,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);
@@ -2819,12 +2819,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_opts);
+    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/include/block/block.h b/include/block/block.h
index 9dc6aad..6e73277 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -125,9 +125,8 @@ void bdrv_init_with_whitelist(void);
 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);
+int bdrv_create(BlockDriver *drv, const char* filename, QemuOpts *opts);
+int bdrv_create_file(const char *filename, QemuOpts *opts);
 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 9aa98b5..a44a9ac 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -95,7 +95,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 *opts);
     int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
     int (*bdrv_make_empty)(BlockDriverState *bs);
     /* aio */
@@ -184,9 +184,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_opts;
 
     /*
      * Returns 0 for completed check, -errno for internal errors.
diff --git a/qemu-img.c b/qemu-img.c
index 31627b0..3eac10c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -229,7 +229,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_opts = NULL;
 
     /* Find driver and parse its options */
     drv = bdrv_find_format(fmt);
@@ -244,12 +244,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_opts = qemu_opts_append(drv->bdrv_create_opts,
+                                   proto_drv->bdrv_create_opts);
+    qemu_opts_print_help(create_opts);
+    qemu_opts_free(create_opts);
     return 0;
 }
 
@@ -301,19 +299,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;
@@ -1120,8 +1118,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_opts = NULL;
+    const char *out_baseimg_param;
     char *options = NULL;
     const char *snapshot_name = NULL;
     float local_progress = 0;
@@ -1265,40 +1264,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_opts = qemu_opts_append(drv->bdrv_create_opts,
+                                   proto_drv->bdrv_create_opts);
 
     if (options) {
-        param = parse_option_parameters(options, create_options, param);
-        if (param == NULL) {
+        if (qemu_opts_do_parse_replace(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_opts);
     }
-
-    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");
@@ -1306,15 +1301,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");
@@ -1532,8 +1527,10 @@ static int img_convert(int argc, char **argv)
     }
 out:
     qemu_progress_end();
-    free_option_parameters(create_options);
-    free_option_parameters(param);
+    qemu_opts_free(create_opts);
+    if (param) {
+        qemu_opts_del(param);
+    }
     qemu_vfree(buf);
     if (out_bs) {
         bdrv_delete(out_bs);
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH V13 6/6] remove QEMUOptionParameter related functions and struct
  2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
                   ` (4 preceding siblings ...)
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 5/6] Use QemuOpts support in block layer Dong Xu Wang
@ 2013-04-10  6:25 ` Dong Xu Wang
  2013-04-22  2:20 ` [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
  2013-05-06 12:26 ` Markus Armbruster
  7 siblings, 0 replies; 16+ messages in thread
From: Dong Xu Wang @ 2013-04-10  6:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, Dong Xu Wang, wdongxu, armbru, stefanha


Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
---
 include/qemu/option.h |  32 ------
 util/qemu-option.c    | 285 --------------------------------------------------
 2 files changed, 317 deletions(-)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index d63e447..51814cf 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -38,17 +38,6 @@ enum QEMUOptionParType {
     OPT_STRING,
 };
 
-typedef struct QEMUOptionParameter {
-    const char *name;
-    enum QEMUOptionParType type;
-    union {
-        uint64_t n;
-        char* s;
-    } value;
-    const char *help;
-} QEMUOptionParameter;
-
-
 const char *get_opt_name(char *buf, int buf_size, const char *p, char delim);
 const char *get_opt_value(char *buf, int buf_size, const char *p);
 int get_next_param_value(char *buf, int buf_size,
@@ -58,27 +47,6 @@ int get_param_value(char *buf, int buf_size,
 int check_params(char *buf, int buf_size,
                  const char * const *params, const char *str);
 
-
-/*
- * The following functions take a parameter list as input. This is a pointer to
- * the first element of a QEMUOptionParameter array which is terminated by an
- * entry with entry->name == NULL.
- */
-
-QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
-    const char *name);
-int set_option_parameter(QEMUOptionParameter *list, const char *name,
-    const char *value);
-int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
-    uint64_t value);
-QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
-    QEMUOptionParameter *list);
-QEMUOptionParameter *parse_option_parameters(const char *param,
-    QEMUOptionParameter *list, QEMUOptionParameter *dest);
-void free_option_parameters(QEMUOptionParameter *list);
-void print_option_parameters(QEMUOptionParameter *list);
-void print_option_help(QEMUOptionParameter *list);
-
 /* ------------------------------------------------------------------ */
 
 typedef struct QemuOpt QemuOpt;
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 5db6d76..8a4f644 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -155,22 +155,6 @@ int check_params(char *buf, int buf_size,
     return 0;
 }
 
-/*
- * Searches an option list for an option with the given name
- */
-QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
-    const char *name)
-{
-    while (list && list->name) {
-        if (!strcmp(list->name, name)) {
-            return list;
-        }
-        list++;
-    }
-
-    return NULL;
-}
-
 static void parse_option_bool(const char *name, const char *value, bool *ret,
                               Error **errp)
 {
@@ -244,275 +228,6 @@ static void parse_option_size(const char *name, const char *value,
     }
 }
 
-/*
- * Sets the value of a parameter in a given option list. The parsing of the
- * value depends on the type of option:
- *
- * OPT_FLAG (uses value.n):
- *      If no value is given, the flag is set to 1.
- *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
- *
- * OPT_STRING (uses value.s):
- *      value is strdup()ed and assigned as option value
- *
- * OPT_SIZE (uses value.n):
- *      The value is converted to an integer. Suffixes for kilobytes etc. are
- *      allowed (powers of 1024).
- *
- * Returns 0 on succes, -1 in error cases
- */
-int set_option_parameter(QEMUOptionParameter *list, const char *name,
-    const char *value)
-{
-    bool flag;
-    Error *local_err = NULL;
-
-    // Find a matching parameter
-    list = get_option_parameter(list, name);
-    if (list == NULL) {
-        fprintf(stderr, "Unknown option '%s'\n", name);
-        return -1;
-    }
-
-    // Process parameter
-    switch (list->type) {
-    case OPT_FLAG:
-        parse_option_bool(name, value, &flag, &local_err);
-        if (!error_is_set(&local_err)) {
-            list->value.n = flag;
-        }
-        break;
-
-    case OPT_STRING:
-        if (value != NULL) {
-            list->value.s = g_strdup(value);
-        } else {
-            fprintf(stderr, "Option '%s' needs a parameter\n", name);
-            return -1;
-        }
-        break;
-
-    case OPT_SIZE:
-        parse_option_size(name, value, &list->value.n, &local_err);
-        break;
-
-    default:
-        fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
-        return -1;
-    }
-
-    if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
-    }
-
-    return 0;
-}
-
-/*
- * Sets the given parameter to an integer instead of a string.
- * This function cannot be used to set string options.
- *
- * Returns 0 on success, -1 in error cases
- */
-int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
-    uint64_t value)
-{
-    // Find a matching parameter
-    list = get_option_parameter(list, name);
-    if (list == NULL) {
-        fprintf(stderr, "Unknown option '%s'\n", name);
-        return -1;
-    }
-
-    // Process parameter
-    switch (list->type) {
-    case OPT_FLAG:
-    case OPT_NUMBER:
-    case OPT_SIZE:
-        list->value.n = value;
-        break;
-
-    default:
-        return -1;
-    }
-
-    return 0;
-}
-
-/*
- * Frees a option list. If it contains strings, the strings are freed as well.
- */
-void free_option_parameters(QEMUOptionParameter *list)
-{
-    QEMUOptionParameter *cur = list;
-
-    while (cur && cur->name) {
-        if (cur->type == OPT_STRING) {
-            g_free(cur->value.s);
-        }
-        cur++;
-    }
-
-    g_free(list);
-}
-
-/*
- * Count valid options in list
- */
-static size_t count_option_parameters(QEMUOptionParameter *list)
-{
-    size_t num_options = 0;
-
-    while (list && list->name) {
-        num_options++;
-        list++;
-    }
-
-    return num_options;
-}
-
-/*
- * Append an option list (list) to an option list (dest).
- *
- * If dest is NULL, a new copy of list is created.
- *
- * Returns a pointer to the first element of dest (or the newly allocated copy)
- */
-QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
-    QEMUOptionParameter *list)
-{
-    size_t num_options, num_dest_options;
-
-    num_options = count_option_parameters(dest);
-    num_dest_options = num_options;
-
-    num_options += count_option_parameters(list);
-
-    dest = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
-    dest[num_dest_options].name = NULL;
-
-    while (list && list->name) {
-        if (get_option_parameter(dest, list->name) == NULL) {
-            dest[num_dest_options++] = *list;
-            dest[num_dest_options].name = NULL;
-        }
-        list++;
-    }
-
-    return dest;
-}
-
-/*
- * Parses a parameter string (param) into an option list (dest).
- *
- * list is the template option list. If dest is NULL, a new copy of list is
- * created. If list is NULL, this function fails.
- *
- * A parameter string consists of one or more parameters, separated by commas.
- * Each parameter consists of its name and possibly of a value. In the latter
- * case, the value is delimited by an = character. To specify a value which
- * contains commas, double each comma so it won't be recognized as the end of
- * the parameter.
- *
- * For more details of the parsing see above.
- *
- * Returns a pointer to the first element of dest (or the newly allocated copy)
- * or NULL in error cases
- */
-QEMUOptionParameter *parse_option_parameters(const char *param,
-    QEMUOptionParameter *list, QEMUOptionParameter *dest)
-{
-    QEMUOptionParameter *allocated = NULL;
-    char name[256];
-    char value[256];
-    char *param_delim, *value_delim;
-    char next_delim;
-
-    if (list == NULL) {
-        return NULL;
-    }
-
-    if (dest == NULL) {
-        dest = allocated = append_option_parameters(NULL, list);
-    }
-
-    while (*param) {
-
-        // Find parameter name and value in the string
-        param_delim = strchr(param, ',');
-        value_delim = strchr(param, '=');
-
-        if (value_delim && (value_delim < param_delim || !param_delim)) {
-            next_delim = '=';
-        } else {
-            next_delim = ',';
-            value_delim = NULL;
-        }
-
-        param = get_opt_name(name, sizeof(name), param, next_delim);
-        if (value_delim) {
-            param = get_opt_value(value, sizeof(value), param + 1);
-        }
-        if (*param != '\0') {
-            param++;
-        }
-
-        // Set the parameter
-        if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
-            goto fail;
-        }
-    }
-
-    return dest;
-
-fail:
-    // Only free the list if it was newly allocated
-    free_option_parameters(allocated);
-    return NULL;
-}
-
-/*
- * Prints all options of a list that have a value to stdout
- */
-void print_option_parameters(QEMUOptionParameter *list)
-{
-    while (list && list->name) {
-        switch (list->type) {
-            case OPT_STRING:
-                 if (list->value.s != NULL) {
-                     printf("%s='%s' ", list->name, list->value.s);
-                 }
-                break;
-            case OPT_FLAG:
-                printf("%s=%s ", list->name, list->value.n ? "on" : "off");
-                break;
-            case OPT_SIZE:
-            case OPT_NUMBER:
-                printf("%s=%" PRId64 " ", list->name, list->value.n);
-                break;
-            default:
-                printf("%s=(unknown type) ", list->name);
-                break;
-        }
-        list++;
-    }
-}
-
-/*
- * Prints an overview of all available options
- */
-void print_option_help(QEMUOptionParameter *list)
-{
-    printf("Supported options:\n");
-    while (list && list->name) {
-        printf("%-16s %s\n", list->name,
-            list->help ? list->help : "No description available");
-        list++;
-    }
-}
-
 /* ------------------------------------------------------------------ */
 
 static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser
  2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
                   ` (5 preceding siblings ...)
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 6/6] remove QEMUOptionParameter related functions and struct Dong Xu Wang
@ 2013-04-22  2:20 ` Dong Xu Wang
  2013-04-22  8:18   ` Markus Armbruster
  2013-05-06 12:26 ` Markus Armbruster
  7 siblings, 1 reply; 16+ messages in thread
From: Dong Xu Wang @ 2013-04-22  2:20 UTC (permalink / raw)
  To: Dong Xu Wang; +Cc: kwolf, wdongxu, qemu-devel, stefanha, armbru

On 2013/4/10 14:25, Dong Xu Wang wrote:
> These patches will replace QEMUOptionParameter with QemuOpts. Change logs
> please go to each patch's commit message.
>
> Dong Xu Wang (6):
>    add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print
>    avoid duplication of default value in QemuOpts
>    Create four QemuOptsList related functions
>    create some QemuOpts functons
>    Use QemuOpts support in block layer
>    remove QEMUOptionParameter related functions and struct
>
>   block.c                   |  98 ++++----
>   block/cow.c               |  46 ++--
>   block/gluster.c           |  37 ++--
>   block/iscsi.c             |  35 ++-
>   block/qcow.c              |  61 +++--
>   block/qcow2.c             | 173 ++++++++-------
>   block/qed.c               |  86 ++++---
>   block/qed.h               |   2 +-
>   block/raw-posix.c         |  59 +++--
>   block/raw-win32.c         |  31 +--
>   block/raw.c               |  30 +--
>   block/rbd.c               |  62 +++---
>   block/sheepdog.c          |  79 ++++---
>   block/vdi.c               |  70 +++---
>   block/vmdk.c              |  90 ++++----
>   block/vpc.c               |  57 ++---
>   block/vvfat.c             |  11 +-
>   include/block/block.h     |   5 +-
>   include/block/block_int.h |   6 +-
>   include/qemu/option.h     |  49 ++--
>   qemu-img.c                |  61 +++--
>   util/qemu-option.c        | 555 ++++++++++++++++++++--------------------------
>   22 files changed, 791 insertions(+), 912 deletions(-)
>
Ping..
Can anyone give some comments? That will be very grateful..

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser
  2013-04-22  2:20 ` [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
@ 2013-04-22  8:18   ` Markus Armbruster
  0 siblings, 0 replies; 16+ messages in thread
From: Markus Armbruster @ 2013-04-22  8:18 UTC (permalink / raw)
  To: Dong Xu Wang; +Cc: kwolf, wdongxu, qemu-devel, stefanha

Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:

> On 2013/4/10 14:25, Dong Xu Wang wrote:
>> These patches will replace QEMUOptionParameter with QemuOpts. Change logs
>> please go to each patch's commit message.
>>
>> Dong Xu Wang (6):
>>    add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print
>>    avoid duplication of default value in QemuOpts
>>    Create four QemuOptsList related functions
>>    create some QemuOpts functons
>>    Use QemuOpts support in block layer
>>    remove QEMUOptionParameter related functions and struct
>>
>>   block.c                   |  98 ++++----
>>   block/cow.c               |  46 ++--
>>   block/gluster.c           |  37 ++--
>>   block/iscsi.c             |  35 ++-
>>   block/qcow.c              |  61 +++--
>>   block/qcow2.c             | 173 ++++++++-------
>>   block/qed.c               |  86 ++++---
>>   block/qed.h               |   2 +-
>>   block/raw-posix.c         |  59 +++--
>>   block/raw-win32.c         |  31 +--
>>   block/raw.c               |  30 +--
>>   block/rbd.c               |  62 +++---
>>   block/sheepdog.c          |  79 ++++---
>>   block/vdi.c               |  70 +++---
>>   block/vmdk.c              |  90 ++++----
>>   block/vpc.c               |  57 ++---
>>   block/vvfat.c             |  11 +-
>>   include/block/block.h     |   5 +-
>>   include/block/block_int.h |   6 +-
>>   include/qemu/option.h     |  49 ++--
>>   qemu-img.c                |  61 +++--
>>   util/qemu-option.c        | 555 ++++++++++++++++++++--------------------------
>>   22 files changed, 791 insertions(+), 912 deletions(-)
>>
> Ping..
> Can anyone give some comments? That will be very grateful..

It's in my queue.  Sorry for the delay, I know how frustrating it must
be, but I'm doing what I can.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 2/6] avoid duplication of default value in QemuOpts
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 2/6] avoid duplication of default value in QemuOpts Dong Xu Wang
@ 2013-05-06 11:54   ` Markus Armbruster
  0 siblings, 0 replies; 16+ messages in thread
From: Markus Armbruster @ 2013-05-06 11:54 UTC (permalink / raw)
  To: Dong Xu Wang; +Cc: kwolf, wdongxu, qemu-devel, stefanha

Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:

> According Markus's comments, his patch will move the default value entirely
> to QemuOptDesc.
>
> When getting the value of an option that hasn't been set, and
> QemuOptDesc has a default value, return that.  Else, behave as
> before.
>
> Example: qemu_opt_get_number(opts, "foo", 42)
>
>    If "foo" has been set in opts, return its value.
>
>    Else, if opt's QemuOptDesc has a default value for "foo", return
>    that.
>
>    Else, return 42.
>
>    Note that the last argument is useless when QemuOptDesc has a
>    default value.  Ugly.  If it bothers us, assert that the argument
>    equals the default from QemuOptDesc.

Last sentence is not 100% clear.  Either change it to "If it bothers us,
we could assert", or implement the assert.  Considering we're at v12, I
recommend the former.

>
> Example: qemu_opt_get(opts, "bar")
>
>    If "bar" has been set in opts, return its value.
>
>    Else, if opt's QemuOptDesc has a default value for "bar", return
>    that.
>
>    Else, return NULL.
>
> Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
> ---
>  util/qemu-option.c | 58 +++++++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 40 insertions(+), 18 deletions(-)
>
> diff --git a/util/qemu-option.c b/util/qemu-option.c
> index 57cdd57..4f94000 100644
> --- a/util/qemu-option.c
> +++ b/util/qemu-option.c
> @@ -525,10 +525,28 @@ static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
>      return NULL;
>  }
>  
> +static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
> +                                            const char *name)
> +{
> +    int i;
> +
> +    for (i = 0; desc[i].name != NULL; i++) {
> +        if (strcmp(desc[i].name, name) == 0) {
> +            return &desc[i];
> +        }
> +    }
> +
> +    return NULL;
> +}
> +
>  const char *qemu_opt_get(QemuOpts *opts, const char *name)
>  {
>      QemuOpt *opt = qemu_opt_find(opts, name);
> -    return opt ? opt->str : NULL;
> +    const QemuOptDesc *desc;
> +    desc = find_desc_by_name(opts->list->desc, name);
> +
> +    return opt ? opt->str :
> +        (desc && desc->def_value_str ? desc->def_value_str : NULL);
>  }
>  

I'd make this function work exactly like the ones that follow:

    if (!opt) {
        desc = find_desc_by_name(opts->list->desc, name);
        if (desc && desc->def_value_str) {
            return desc->def_value_str;
        }
    }
    return opt ? opt->str : NULL;

Matter of taste; no need to respin just for that.

>  bool qemu_opt_has_help_opt(QemuOpts *opts)
> @@ -546,9 +564,15 @@ bool qemu_opt_has_help_opt(QemuOpts *opts)
>  bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
>  {
>      QemuOpt *opt = qemu_opt_find(opts, name);
> +    const QemuOptDesc *desc;
>  
> -    if (opt == NULL)
> +    if (opt == NULL) {
> +        desc = find_desc_by_name(opts->list->desc, name);
> +        if (desc && desc->def_value_str) {
> +            parse_option_bool(name, desc->def_value_str, &defval, NULL);

Ignores errors.  Should only happen when somebody sets a bad
desc->def_value_str.  Because those are fixed at compile time, that's a
programming error.  Recommend to assert like this:

            parse_option_bool(name, desc->def_value_str, &defval, &local_err);
            assert(!local_err);

> +        }
>          return defval;
> +    }
>      assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
>      return opt->value.boolean;
>  }
> @@ -556,9 +580,15 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
>  uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
>  {
>      QemuOpt *opt = qemu_opt_find(opts, name);
> +    const QemuOptDesc *desc;
>  
> -    if (opt == NULL)
> +    if (opt == NULL) {
> +        desc = find_desc_by_name(opts->list->desc, name);
> +        if (desc && desc->def_value_str) {
> +            parse_option_number(name, desc->def_value_str, &defval, NULL);

Likewise.

> +        }
>          return defval;
> +    }
>      assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
>      return opt->value.uint;
>  }
> @@ -566,9 +596,15 @@ uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
>  uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
>  {
>      QemuOpt *opt = qemu_opt_find(opts, name);
> +    const QemuOptDesc *desc;
>  
> -    if (opt == NULL)
> +    if (opt == NULL) {
> +        desc = find_desc_by_name(opts->list->desc, name);
> +        if (desc && desc->def_value_str) {
> +            parse_option_size(name, desc->def_value_str, &defval, NULL);

Likewise.

> +        }
>          return defval;
> +    }
>      assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
>      return opt->value.uint;
>  }
> @@ -609,20 +645,6 @@ static bool opts_accepts_any(const QemuOpts *opts)
>      return opts->list->desc[0].name == NULL;
>  }
>  
> -static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
> -                                            const char *name)
> -{
> -    int i;
> -
> -    for (i = 0; desc[i].name != NULL; i++) {
> -        if (strcmp(desc[i].name, name) == 0) {
> -            return &desc[i];
> -        }
> -    }
> -
> -    return NULL;
> -}
> -
>  static void opt_set(QemuOpts *opts, const char *name, const char *value,
>                      bool prepend, Error **errp)
>  {

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 1/6] add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 1/6] add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print Dong Xu Wang
@ 2013-05-06 12:16   ` Markus Armbruster
  0 siblings, 0 replies; 16+ messages in thread
From: Markus Armbruster @ 2013-05-06 12:16 UTC (permalink / raw)
  To: Dong Xu Wang; +Cc: kwolf, wdongxu, qemu-devel, stefanha

Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:

> qemu_opts_print has no user now, so can re-write the function safely.
>
> qemu_opts_print will be used while using "qemu-img create", it will
> produce the same output as previous code.
>
> The behavior of this function has changed:
>
> 1. Print every possible option, whether a value has been set or not.
> 2. Option descriptors may provide a default value.
> 3. Print to stdout instead of stderr.
>
> Previously the behavior was to print every option that has been set.
> Options that have not been set would be skipped.
>
> Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
> ---
> v12->v13
> 1) re-write commit message.
>
> v11->v12
> 1) make def_value_str become the real default value string in opt_set
> function.
>
> v10->v11:
> 1) print all values that have actually been assigned while accept-any
> cases.
>
> v7->v8:
> 1) print "elements => accept any params" while opts_accepts_any() ==
> true.
> 2) since def_print_str is the default value if an option isn't set,
> so rename it to def_value_str.
>
>
>  include/qemu/option.h |  3 ++-
>  util/qemu-option.c    | 33 +++++++++++++++++++++++++++------
>  2 files changed, 29 insertions(+), 7 deletions(-)
>
> diff --git a/include/qemu/option.h b/include/qemu/option.h
> index bdb6d21..b928ab0 100644
> --- a/include/qemu/option.h
> +++ b/include/qemu/option.h
> @@ -96,6 +96,7 @@ typedef struct QemuOptDesc {
>      const char *name;
>      enum QemuOptType type;
>      const char *help;
> +    const char *def_value_str;
>  } QemuOptDesc;
>  
>  struct QemuOptsList {
> @@ -152,7 +153,7 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
>  void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp);
>  
>  typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
> -int qemu_opts_print(QemuOpts *opts, void *dummy);
> +int qemu_opts_print(QemuOpts *opts);
>  int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
>                        int abort_on_failure);
>  
> diff --git a/util/qemu-option.c b/util/qemu-option.c
> index 8b74bf1..57cdd57 100644
> --- a/util/qemu-option.c
> +++ b/util/qemu-option.c
> @@ -646,6 +646,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>      }
>      opt->desc = desc;
>      opt->str = g_strdup(value);
> +    opt->str = g_strdup(value ?: desc->def_value_str);

Memory leak.  Did you forget to delete the previous line?  You do it in
PATCH 4/6, plugging the leak...

>      qemu_opt_parse(opt, &local_err);
>      if (error_is_set(&local_err)) {
>          error_propagate(errp, local_err);

opt_set() now accepts a null value argument, and so do its callers
qemu_opt_set(), qemu_opt_set_err(), qemu_opts_set().  Why?

> @@ -860,16 +861,36 @@ void qemu_opts_del(QemuOpts *opts)
>      g_free(opts);
>  }
>  
> -int qemu_opts_print(QemuOpts *opts, void *dummy)
> +int qemu_opts_print(QemuOpts *opts)
>  {
>      QemuOpt *opt;
> +    QemuOptDesc *desc = opts->list->desc;
>  
> -    fprintf(stderr, "%s: %s:", opts->list->name,
> -            opts->id ? opts->id : "<noid>");
> -    QTAILQ_FOREACH(opt, &opts->head, next) {
> -        fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
> +    if (desc[0].name == NULL) {
> +        QTAILQ_FOREACH(opt, &opts->head, next) {
> +            printf("%s=\"%s\" ", opt->name, opt->str);
> +        }
> +        return 0;
> +    }
> +    for (; desc && desc->name; desc++) {
> +        const char *value = desc->def_value_str;
> +        QemuOpt *opt;
> +
> +        opt = qemu_opt_find(opts, desc->name);
> +        if (opt) {
> +            value = opt->str;
> +        }
> +
> +        if (!value) {
> +            continue;
> +        }
> +
> +        if (desc->type == QEMU_OPT_STRING) {
> +            printf("%s='%s' ", desc->name, value);
> +        } else {
> +            printf("%s=%s ", desc->name, value);
> +        }
>      }
> -    fprintf(stderr, "\n");
>      return 0;
>  }

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons
  2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons Dong Xu Wang
@ 2013-05-06 12:20   ` Markus Armbruster
  2013-05-07  5:19     ` Dong Xu Wang
  0 siblings, 1 reply; 16+ messages in thread
From: Markus Armbruster @ 2013-05-06 12:20 UTC (permalink / raw)
  To: Dong Xu Wang; +Cc: kwolf, wdongxu, qemu-devel, stefanha

Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:

> These functions will be used in next commit. qemu_opt_get_(*)_del functions
> are used to make sure we have the same behaviors as before: after get an
> option value, options++.

I don't understand the last sentence.

> Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
> ---
>  include/qemu/option.h |  11 +++++-
>  util/qemu-option.c    | 103 ++++++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 105 insertions(+), 9 deletions(-)
>
> diff --git a/include/qemu/option.h b/include/qemu/option.h
> index c7a5c14..d63e447 100644
> --- a/include/qemu/option.h
> +++ b/include/qemu/option.h
> @@ -108,6 +108,7 @@ struct QemuOptsList {
>  };
>  
>  const char *qemu_opt_get(QemuOpts *opts, const char *name);
> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name);
>  /**
>   * qemu_opt_has_help_opt:
>   * @opts: options to search for a help request
> @@ -121,13 +122,18 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name);
>   */
>  bool qemu_opt_has_help_opt(QemuOpts *opts);
>  bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
>  uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
>  uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
> +                               uint64_t defval);
>  int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value);
>  void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>                        Error **errp);
>  int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
>  int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val);
> +int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val);
>  typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
>  int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
>                       int abort_on_failure);
> @@ -144,7 +150,10 @@ const char *qemu_opts_id(QemuOpts *opts);
>  void qemu_opts_del(QemuOpts *opts);
>  void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
>  int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
> -QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
> +                               const char *firstname);
> +QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
> +                          int permit_abbrev);
>  void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
>                              int permit_abbrev);
>  QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
> diff --git a/util/qemu-option.c b/util/qemu-option.c
> index 0488c27..5db6d76 100644
> --- a/util/qemu-option.c
> +++ b/util/qemu-option.c
> @@ -33,6 +33,8 @@
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/option_int.h"
>  
> +static void qemu_opt_del(QemuOpt *opt);
> +
>  /*
>   * Extracts the name of an option from the parameter string (p points at the
>   * first byte of the option name)
> @@ -549,6 +551,16 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
   const char *qemu_opt_get(QemuOpts *opts, const char *name)
   {
       QemuOpt *opt = qemu_opt_find(opts, name);
       const QemuOptDesc *desc;
       desc = find_desc_by_name(opts->list->desc, name);

       return opt ? opt->str :
>          (desc && desc->def_value_str ? desc->def_value_str : NULL);
>  }
>  
> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name)
> +{
> +    QemuOpt *opt = qemu_opt_find(opts, name);
> +    const char *str = opt ? g_strdup(opt->str) : NULL;
> +    if (opt) {
> +        qemu_opt_del(opt);
> +    }
> +    return str;
> +}
> +

Unlike qemu_opt_del(), this one doesn't use def_value_str.  Why?  Isn't
that a trap for users of this function?

Same question for the qemu_opt_get_FOO_del() that follow.

>  bool qemu_opt_has_help_opt(QemuOpts *opts)
>  {
>      QemuOpt *opt;
> @@ -577,6 +589,22 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
>      return opt->value.boolean;
>  }
>  
> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
> +{
> +    QemuOpt *opt = qemu_opt_find(opts, name);
> +    bool ret;
> +
> +    if (opt == NULL) {
> +        return defval;
> +    }
> +    ret = opt->value.boolean;
> +    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
> +    if (opt) {
> +        qemu_opt_del(opt);
> +    }
> +    return ret;
> +}
> +
>  uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
>  {
>      QemuOpt *opt = qemu_opt_find(opts, name);
> @@ -609,6 +637,23 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
>      return opt->value.uint;
>  }
>  
> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
> +                               uint64_t defval)
> +{
> +    QemuOpt *opt = qemu_opt_find(opts, name);
> +    uint64_t ret;
> +
> +    if (opt == NULL) {
> +        return defval;
> +    }
> +    ret = opt->value.uint;
> +    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
> +    if (opt) {
> +        qemu_opt_del(opt);
> +    }
> +    return ret;
> +}
> +
>  static void qemu_opt_parse(QemuOpt *opt, Error **errp)
>  {
>      if (opt->desc == NULL)
> @@ -646,7 +691,7 @@ static bool opts_accepts_any(const QemuOpts *opts)
>  }
>  
>  static void opt_set(QemuOpts *opts, const char *name, const char *value,
> -                    bool prepend, Error **errp)
> +                    bool prepend, bool replace, Error **errp)
>  {
>      QemuOpt *opt;
>      const QemuOptDesc *desc;
> @@ -658,6 +703,11 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>          return;
>      }
>  
> +    opt = qemu_opt_find(opts, name);
> +    if (replace && opt) {
> +        qemu_opt_del(opt);
> +    }
> +
>      opt = g_malloc0(sizeof(*opt));
>      opt->name = g_strdup(name);
>      opt->opts = opts;
> @@ -667,7 +717,6 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>          QTAILQ_INSERT_TAIL(&opts->head, opt, next);
>      }
>      opt->desc = desc;
> -    opt->str = g_strdup(value);
>      opt->str = g_strdup(value ?: desc->def_value_str);
>      qemu_opt_parse(opt, &local_err);
>      if (error_is_set(&local_err)) {

Here you plug the leak you created in PATCH 1/6.

> @@ -680,7 +729,29 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
>  {
>      Error *local_err = NULL;
>  
> -    opt_set(opts, name, value, false, &local_err);
> +    opt_set(opts, name, value, false, false, &local_err);
> +    if (error_is_set(&local_err)) {
> +        qerror_report_err(local_err);
> +        error_free(local_err);
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +/*
> + * If name exists, the function will delete the opt first and then add a new
> + * one.
> + */
> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value)
> +{
> +    Error *local_err = NULL;
> +    QemuOpt *opt = qemu_opt_find(opts, name);
> +
> +    if (opt) {
> +        qemu_opt_del(opt);
> +    }

Why?  Won't opt_set() delete it already?

Same question for the qemu_opt_replace_set_FOO() that follow.

> +    opt_set(opts, name, value, false, true, &local_err);
>      if (error_is_set(&local_err)) {
>          qerror_report_err(local_err);
>          error_free(local_err);
> @@ -693,7 +764,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
>  void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>                        Error **errp)
>  {
> -    opt_set(opts, name, value, false, errp);
> +    opt_set(opts, name, value, false, false, errp);
>  }
>  
>  int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
> @@ -740,6 +811,16 @@ int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val)
>      return 0;
>  }
>  
> +int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val)
> +{
> +    QemuOpt *opt = qemu_opt_find(opts, name);
> +
> +    if (opt) {
> +        qemu_opt_del(opt);
> +    }
> +    return qemu_opt_set_number(opts, name, val);
> +}
> +
>  int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
>                       int abort_on_failure)
>  {
> @@ -917,7 +998,7 @@ int qemu_opts_print(QemuOpts *opts)
>  }
>  
>  static int opts_do_parse(QemuOpts *opts, const char *params,
> -                         const char *firstname, bool prepend)
> +                         const char *firstname, bool prepend, bool replace)
>  {
>      char option[128], value[1024];
>      const char *p,*pe,*pc;
> @@ -953,7 +1034,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
>          }
>          if (strcmp(option, "id") != 0) {
>              /* store and parse */
> -            opt_set(opts, option, value, prepend, &local_err);
> +            opt_set(opts, option, value, prepend, replace, &local_err);
>              if (error_is_set(&local_err)) {
>                  qerror_report_err(local_err);
>                  error_free(local_err);
> @@ -969,7 +1050,13 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
>  
>  int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
>  {
> -    return opts_do_parse(opts, params, firstname, false);
> +    return opts_do_parse(opts, params, firstname, false, false);
> +}
> +
> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
> +                               const char *firstname)
> +{
> +    return opts_do_parse(opts, params, firstname, false, true);
>  }
>  
>  static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
> @@ -1008,7 +1095,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>          return NULL;
>      }
>  
> -    if (opts_do_parse(opts, params, firstname, defaults) != 0) {
> +    if (opts_do_parse(opts, params, firstname, defaults, false) != 0) {
>          qemu_opts_del(opts);
>          return NULL;
>      }

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser
  2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
                   ` (6 preceding siblings ...)
  2013-04-22  2:20 ` [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
@ 2013-05-06 12:26 ` Markus Armbruster
  7 siblings, 0 replies; 16+ messages in thread
From: Markus Armbruster @ 2013-05-06 12:26 UTC (permalink / raw)
  To: Dong Xu Wang; +Cc: kwolf, wdongxu, qemu-devel, stefanha

Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:

> These patches will replace QEMUOptionParameter with QemuOpts. Change logs
> please go to each patch's commit message.

I reviewed 1-4/6 for now.  I'm sorry it has taken me so long.  Let's
discuss my findings before I continue with 5/6, because that one's
*big*.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons
  2013-05-06 12:20   ` Markus Armbruster
@ 2013-05-07  5:19     ` Dong Xu Wang
  2013-05-07  7:38       ` Markus Armbruster
  0 siblings, 1 reply; 16+ messages in thread
From: Dong Xu Wang @ 2013-05-07  5:19 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, wdongxu, qemu-devel, stefanha

On 2013/5/6 20:20, Markus Armbruster wrote:
> Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:
>
>> These functions will be used in next commit. qemu_opt_get_(*)_del functions
>> are used to make sure we have the same behaviors as before: after get an
>> option value, options++.
>
> I don't understand the last sentence.
>
>> Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
>> ---
>>   include/qemu/option.h |  11 +++++-
>>   util/qemu-option.c    | 103 ++++++++++++++++++++++++++++++++++++++++++++++----
>>   2 files changed, 105 insertions(+), 9 deletions(-)
>>
>> diff --git a/include/qemu/option.h b/include/qemu/option.h
>> index c7a5c14..d63e447 100644
>> --- a/include/qemu/option.h
>> +++ b/include/qemu/option.h
>> @@ -108,6 +108,7 @@ struct QemuOptsList {
>>   };
>>
>>   const char *qemu_opt_get(QemuOpts *opts, const char *name);
>> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name);
>>   /**
>>    * qemu_opt_has_help_opt:
>>    * @opts: options to search for a help request
>> @@ -121,13 +122,18 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name);
>>    */
>>   bool qemu_opt_has_help_opt(QemuOpts *opts);
>>   bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
>> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
>>   uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
>>   uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
>> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
>> +                               uint64_t defval);
>>   int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
>> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value);
>>   void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>>                         Error **errp);
>>   int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
>>   int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val);
>> +int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val);
>>   typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
>>   int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
>>                        int abort_on_failure);
>> @@ -144,7 +150,10 @@ const char *qemu_opts_id(QemuOpts *opts);
>>   void qemu_opts_del(QemuOpts *opts);
>>   void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
>>   int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
>> -QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
>> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
>> +                               const char *firstname);
>> +QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
>> +                          int permit_abbrev);
>>   void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
>>                               int permit_abbrev);
>>   QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
>> diff --git a/util/qemu-option.c b/util/qemu-option.c
>> index 0488c27..5db6d76 100644
>> --- a/util/qemu-option.c
>> +++ b/util/qemu-option.c
>> @@ -33,6 +33,8 @@
>>   #include "qapi/qmp/qerror.h"
>>   #include "qemu/option_int.h"
>>
>> +static void qemu_opt_del(QemuOpt *opt);
>> +
>>   /*
>>    * Extracts the name of an option from the parameter string (p points at the
>>    * first byte of the option name)
>> @@ -549,6 +551,16 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
>     const char *qemu_opt_get(QemuOpts *opts, const char *name)
>     {
>         QemuOpt *opt = qemu_opt_find(opts, name);
>         const QemuOptDesc *desc;
>         desc = find_desc_by_name(opts->list->desc, name);
>
>         return opt ? opt->str :
>>           (desc && desc->def_value_str ? desc->def_value_str : NULL);
>>   }
>>
>> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name)
>> +{
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +    const char *str = opt ? g_strdup(opt->str) : NULL;
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +    return str;
>> +}
>> +
>
> Unlike qemu_opt_del(), this one doesn't use def_value_str.  Why?  Isn't
> that a trap for users of this function?
>
> Same question for the qemu_opt_get_FOO_del() that follow.
>
>>   bool qemu_opt_has_help_opt(QemuOpts *opts)
>>   {
>>       QemuOpt *opt;
>> @@ -577,6 +589,22 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
>>       return opt->value.boolean;
>>   }
>>
>> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
>> +{
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +    bool ret;
>> +
>> +    if (opt == NULL) {
>> +        return defval;
>> +    }
>> +    ret = opt->value.boolean;
>> +    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +    return ret;
>> +}
>> +
>>   uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
>>   {
>>       QemuOpt *opt = qemu_opt_find(opts, name);
>> @@ -609,6 +637,23 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
>>       return opt->value.uint;
>>   }
>>
>> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
>> +                               uint64_t defval)
>> +{
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +    uint64_t ret;
>> +
>> +    if (opt == NULL) {
>> +        return defval;
>> +    }
>> +    ret = opt->value.uint;
>> +    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +    return ret;
>> +}
>> +
>>   static void qemu_opt_parse(QemuOpt *opt, Error **errp)
>>   {
>>       if (opt->desc == NULL)
>> @@ -646,7 +691,7 @@ static bool opts_accepts_any(const QemuOpts *opts)
>>   }
>>
>>   static void opt_set(QemuOpts *opts, const char *name, const char *value,
>> -                    bool prepend, Error **errp)
>> +                    bool prepend, bool replace, Error **errp)
>>   {
>>       QemuOpt *opt;
>>       const QemuOptDesc *desc;
>> @@ -658,6 +703,11 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>>           return;
>>       }
>>
>> +    opt = qemu_opt_find(opts, name);
>> +    if (replace && opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +
>>       opt = g_malloc0(sizeof(*opt));
>>       opt->name = g_strdup(name);
>>       opt->opts = opts;
>> @@ -667,7 +717,6 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>>           QTAILQ_INSERT_TAIL(&opts->head, opt, next);
>>       }
>>       opt->desc = desc;
>> -    opt->str = g_strdup(value);
>>       opt->str = g_strdup(value ?: desc->def_value_str);
>>       qemu_opt_parse(opt, &local_err);
>>       if (error_is_set(&local_err)) {
>
> Here you plug the leak you created in PATCH 1/6.
>
>> @@ -680,7 +729,29 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
>>   {
>>       Error *local_err = NULL;
>>
>> -    opt_set(opts, name, value, false, &local_err);
>> +    opt_set(opts, name, value, false, false, &local_err);
>> +    if (error_is_set(&local_err)) {
>> +        qerror_report_err(local_err);
>> +        error_free(local_err);
>> +        return -1;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +/*
>> + * If name exists, the function will delete the opt first and then add a new
>> + * one.
>> + */
>> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value)
>> +{
>> +    Error *local_err = NULL;
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>
> Why?  Won't opt_set() delete it already?
>
No, opt_set will not delete it, but add a new opt. In block layer, while 
parsing options, if the parameter is parsed, it should be deleted and 
won't be used again, so I delete it manually.

> Same question for the qemu_opt_replace_set_FOO() that follow.
>
>> +    opt_set(opts, name, value, false, true, &local_err);
>>       if (error_is_set(&local_err)) {
>>           qerror_report_err(local_err);
>>           error_free(local_err);
>> @@ -693,7 +764,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
>>   void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>>                         Error **errp)
>>   {
>> -    opt_set(opts, name, value, false, errp);
>> +    opt_set(opts, name, value, false, false, errp);
>>   }
>>
>>   int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
>> @@ -740,6 +811,16 @@ int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val)
>>       return 0;
>>   }
>>
>> +int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val)
>> +{
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +    return qemu_opt_set_number(opts, name, val);
>> +}
>> +
>>   int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
>>                        int abort_on_failure)
>>   {
>> @@ -917,7 +998,7 @@ int qemu_opts_print(QemuOpts *opts)
>>   }
>>
>>   static int opts_do_parse(QemuOpts *opts, const char *params,
>> -                         const char *firstname, bool prepend)
>> +                         const char *firstname, bool prepend, bool replace)
>>   {
>>       char option[128], value[1024];
>>       const char *p,*pe,*pc;
>> @@ -953,7 +1034,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
>>           }
>>           if (strcmp(option, "id") != 0) {
>>               /* store and parse */
>> -            opt_set(opts, option, value, prepend, &local_err);
>> +            opt_set(opts, option, value, prepend, replace, &local_err);
>>               if (error_is_set(&local_err)) {
>>                   qerror_report_err(local_err);
>>                   error_free(local_err);
>> @@ -969,7 +1050,13 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
>>
>>   int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
>>   {
>> -    return opts_do_parse(opts, params, firstname, false);
>> +    return opts_do_parse(opts, params, firstname, false, false);
>> +}
>> +
>> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
>> +                               const char *firstname)
>> +{
>> +    return opts_do_parse(opts, params, firstname, false, true);
>>   }
>>
>>   static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>> @@ -1008,7 +1095,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>>           return NULL;
>>       }
>>
>> -    if (opts_do_parse(opts, params, firstname, defaults) != 0) {
>> +    if (opts_do_parse(opts, params, firstname, defaults, false) != 0) {
>>           qemu_opts_del(opts);
>>           return NULL;
>>       }
>
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons
  2013-05-07  5:19     ` Dong Xu Wang
@ 2013-05-07  7:38       ` Markus Armbruster
  2013-05-07  7:53         ` Dong Xu Wang
  0 siblings, 1 reply; 16+ messages in thread
From: Markus Armbruster @ 2013-05-07  7:38 UTC (permalink / raw)
  To: Dong Xu Wang; +Cc: kwolf, wdongxu, qemu-devel, stefanha

Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:

> On 2013/5/6 20:20, Markus Armbruster wrote:
>> Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:
>>
>>> These functions will be used in next commit. qemu_opt_get_(*)_del functions
>>> are used to make sure we have the same behaviors as before: after get an
>>> option value, options++.
>>
>> I don't understand the last sentence.
>>
>>> Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
>>> ---
>>>   include/qemu/option.h |  11 +++++-
>>>   util/qemu-option.c    | 103 ++++++++++++++++++++++++++++++++++++++++++++++----
>>>   2 files changed, 105 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/include/qemu/option.h b/include/qemu/option.h
>>> index c7a5c14..d63e447 100644
>>> --- a/include/qemu/option.h
>>> +++ b/include/qemu/option.h
>>> @@ -108,6 +108,7 @@ struct QemuOptsList {
>>>   };
>>>
>>>   const char *qemu_opt_get(QemuOpts *opts, const char *name);
>>> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name);
>>>   /**
>>>    * qemu_opt_has_help_opt:
>>>    * @opts: options to search for a help request
>>> @@ -121,13 +122,18 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name);
>>>    */
>>>   bool qemu_opt_has_help_opt(QemuOpts *opts);
>>>   bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
>>> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
>>>   uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
>>>   uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
>>> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
>>> +                               uint64_t defval);
>>>   int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
>>> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value);
>>>   void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>>>                         Error **errp);
>>>   int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
>>>   int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val);
>>> +int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val);
>>>   typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
>>>   int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
>>>                        int abort_on_failure);
>>> @@ -144,7 +150,10 @@ const char *qemu_opts_id(QemuOpts *opts);
>>>   void qemu_opts_del(QemuOpts *opts);
>>>   void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
>>>   int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
>>> -QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
>>> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
>>> +                               const char *firstname);
>>> +QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
>>> +                          int permit_abbrev);
>>>   void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
>>>                               int permit_abbrev);
>>>   QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
>>> diff --git a/util/qemu-option.c b/util/qemu-option.c
>>> index 0488c27..5db6d76 100644
>>> --- a/util/qemu-option.c
>>> +++ b/util/qemu-option.c
>>> @@ -33,6 +33,8 @@
>>>   #include "qapi/qmp/qerror.h"
>>>   #include "qemu/option_int.h"
>>>
>>> +static void qemu_opt_del(QemuOpt *opt);
>>> +
>>>   /*
>>>    * Extracts the name of an option from the parameter string (p points at the
>>>    * first byte of the option name)
>>> @@ -549,6 +551,16 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
>>     const char *qemu_opt_get(QemuOpts *opts, const char *name)
>>     {
>>         QemuOpt *opt = qemu_opt_find(opts, name);
>>         const QemuOptDesc *desc;
>>         desc = find_desc_by_name(opts->list->desc, name);
>>
>>         return opt ? opt->str :
>>>           (desc && desc->def_value_str ? desc->def_value_str : NULL);
>>>   }
>>>
>>> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name)
>>> +{
>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>> +    const char *str = opt ? g_strdup(opt->str) : NULL;
>>> +    if (opt) {
>>> +        qemu_opt_del(opt);
>>> +    }
>>> +    return str;
>>> +}
>>> +
>>
>> Unlike qemu_opt_del(), this one doesn't use def_value_str.  Why?  Isn't
>> that a trap for users of this function?
>>
>> Same question for the qemu_opt_get_FOO_del() that follow.

I'm still interested in answers :)

>>>   bool qemu_opt_has_help_opt(QemuOpts *opts)
>>>   {
>>>       QemuOpt *opt;
>>> @@ -577,6 +589,22 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
>>>       return opt->value.boolean;
>>>   }
>>>
>>> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
>>> +{
>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>> +    bool ret;
>>> +
>>> +    if (opt == NULL) {
>>> +        return defval;
>>> +    }
>>> +    ret = opt->value.boolean;
>>> +    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
>>> +    if (opt) {
>>> +        qemu_opt_del(opt);
>>> +    }
>>> +    return ret;
>>> +}
>>> +
>>>   uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
>>>   {
>>>       QemuOpt *opt = qemu_opt_find(opts, name);
>>> @@ -609,6 +637,23 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
>>>       return opt->value.uint;
>>>   }
>>>
>>> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
>>> +                               uint64_t defval)
>>> +{
>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>> +    uint64_t ret;
>>> +
>>> +    if (opt == NULL) {
>>> +        return defval;
>>> +    }
>>> +    ret = opt->value.uint;
>>> +    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
>>> +    if (opt) {
>>> +        qemu_opt_del(opt);
>>> +    }
>>> +    return ret;
>>> +}
>>> +
>>>   static void qemu_opt_parse(QemuOpt *opt, Error **errp)
>>>   {
>>>       if (opt->desc == NULL)
>>> @@ -646,7 +691,7 @@ static bool opts_accepts_any(const QemuOpts *opts)
>>>   }
>>>
>>>   static void opt_set(QemuOpts *opts, const char *name, const char *value,
>>> -                    bool prepend, Error **errp)
>>> +                    bool prepend, bool replace, Error **errp)
>>>   {
>>>       QemuOpt *opt;
>>>       const QemuOptDesc *desc;
>>> @@ -658,6 +703,11 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>>>           return;
>>>       }
>>>
>>> +    opt = qemu_opt_find(opts, name);
>>> +    if (replace && opt) {
>>> +        qemu_opt_del(opt);
>>> +    }
>>> +
>>>       opt = g_malloc0(sizeof(*opt));
>>>       opt->name = g_strdup(name);
>>>       opt->opts = opts;
>>> @@ -667,7 +717,6 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>>>           QTAILQ_INSERT_TAIL(&opts->head, opt, next);
>>>       }
>>>       opt->desc = desc;
>>> -    opt->str = g_strdup(value);
>>>       opt->str = g_strdup(value ?: desc->def_value_str);
>>>       qemu_opt_parse(opt, &local_err);
>>>       if (error_is_set(&local_err)) {
>>
>> Here you plug the leak you created in PATCH 1/6.
>>
>>> @@ -680,7 +729,29 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
>>>   {
>>>       Error *local_err = NULL;
>>>
>>> -    opt_set(opts, name, value, false, &local_err);
>>> +    opt_set(opts, name, value, false, false, &local_err);
>>> +    if (error_is_set(&local_err)) {
>>> +        qerror_report_err(local_err);
>>> +        error_free(local_err);
>>> +        return -1;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +/*
>>> + * If name exists, the function will delete the opt first and then add a new
>>> + * one.
>>> + */
>>> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value)
>>> +{
>>> +    Error *local_err = NULL;
>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>> +
>>> +    if (opt) {
>>> +        qemu_opt_del(opt);
>>> +    }
>>
>> Why?  Won't opt_set() delete it already?
>>
> No, opt_set will not delete it, but add a new opt. In block layer,

Then I'm confused...

> while parsing options, if the parameter is parsed, it should be
> deleted and won't be used again, so I delete it manually.
>
>> Same question for the qemu_opt_replace_set_FOO() that follow.
>>
>>> +    opt_set(opts, name, value, false, true, &local_err);

... because here you pass true for parameter replace, which I (naively?)
expect to delete the option.  Can you unconfuse me?

>>>       if (error_is_set(&local_err)) {
>>>           qerror_report_err(local_err);
>>>           error_free(local_err);
>>> @@ -693,7 +764,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
>>>   void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>>>                         Error **errp)
>>>   {
>>> -    opt_set(opts, name, value, false, errp);
>>> +    opt_set(opts, name, value, false, false, errp);
>>>   }
>>>
>>>   int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
>>> @@ -740,6 +811,16 @@ int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val)
>>>       return 0;
>>>   }
>>>
>>> +int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val)
>>> +{
>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>> +
>>> +    if (opt) {
>>> +        qemu_opt_del(opt);
>>> +    }
>>> +    return qemu_opt_set_number(opts, name, val);
>>> +}
>>> +
>>>   int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
>>>                        int abort_on_failure)
>>>   {
>>> @@ -917,7 +998,7 @@ int qemu_opts_print(QemuOpts *opts)
>>>   }
>>>
>>>   static int opts_do_parse(QemuOpts *opts, const char *params,
>>> -                         const char *firstname, bool prepend)
>>> +                         const char *firstname, bool prepend, bool replace)
>>>   {
>>>       char option[128], value[1024];
>>>       const char *p,*pe,*pc;
>>> @@ -953,7 +1034,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
>>>           }
>>>           if (strcmp(option, "id") != 0) {
>>>               /* store and parse */
>>> -            opt_set(opts, option, value, prepend, &local_err);
>>> +            opt_set(opts, option, value, prepend, replace, &local_err);
>>>               if (error_is_set(&local_err)) {
>>>                   qerror_report_err(local_err);
>>>                   error_free(local_err);
>>> @@ -969,7 +1050,13 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
>>>
>>>   int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
>>>   {
>>> -    return opts_do_parse(opts, params, firstname, false);
>>> +    return opts_do_parse(opts, params, firstname, false, false);
>>> +}
>>> +
>>> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
>>> +                               const char *firstname)
>>> +{
>>> +    return opts_do_parse(opts, params, firstname, false, true);
>>>   }
>>>
>>>   static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>>> @@ -1008,7 +1095,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>>>           return NULL;
>>>       }
>>>
>>> -    if (opts_do_parse(opts, params, firstname, defaults) != 0) {
>>> +    if (opts_do_parse(opts, params, firstname, defaults, false) != 0) {
>>>           qemu_opts_del(opts);
>>>           return NULL;
>>>       }
>>
>>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons
  2013-05-07  7:38       ` Markus Armbruster
@ 2013-05-07  7:53         ` Dong Xu Wang
  0 siblings, 0 replies; 16+ messages in thread
From: Dong Xu Wang @ 2013-05-07  7:53 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, wdongxu, qemu-devel, stefanha

On 2013/5/7 15:38, Markus Armbruster wrote:
> Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:
>
>> On 2013/5/6 20:20, Markus Armbruster wrote:
>>> Dong Xu Wang <wdongxu@linux.vnet.ibm.com> writes:
>>>
>>>> These functions will be used in next commit. qemu_opt_get_(*)_del functions
>>>> are used to make sure we have the same behaviors as before: after get an
>>>> option value, options++.
>>>
>>> I don't understand the last sentence.
>>>
I will make the sentence clear next version.

In block layer, I created 2 series of functions:
1) one is qemu_opt_get_del series, it is used to parse create options, 
after parsing one parameter, will delete it.
2) the other is qemu_opt_replace_set series, it will delete related opt 
and then add a new one.

>>>> Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
>>>> ---
>>>>    include/qemu/option.h |  11 +++++-
>>>>    util/qemu-option.c    | 103 ++++++++++++++++++++++++++++++++++++++++++++++----
>>>>    2 files changed, 105 insertions(+), 9 deletions(-)
>>>>
>>>> diff --git a/include/qemu/option.h b/include/qemu/option.h
>>>> index c7a5c14..d63e447 100644
>>>> --- a/include/qemu/option.h
>>>> +++ b/include/qemu/option.h
>>>> @@ -108,6 +108,7 @@ struct QemuOptsList {
>>>>    };
>>>>
>>>>    const char *qemu_opt_get(QemuOpts *opts, const char *name);
>>>> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name);
>>>>    /**
>>>>     * qemu_opt_has_help_opt:
>>>>     * @opts: options to search for a help request
>>>> @@ -121,13 +122,18 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name);
>>>>     */
>>>>    bool qemu_opt_has_help_opt(QemuOpts *opts);
>>>>    bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
>>>> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
>>>>    uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
>>>>    uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
>>>> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
>>>> +                               uint64_t defval);
>>>>    int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
>>>> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value);
>>>>    void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>>>>                          Error **errp);
>>>>    int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
>>>>    int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val);
>>>> +int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val);
>>>>    typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
>>>>    int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
>>>>                         int abort_on_failure);
>>>> @@ -144,7 +150,10 @@ const char *qemu_opts_id(QemuOpts *opts);
>>>>    void qemu_opts_del(QemuOpts *opts);
>>>>    void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
>>>>    int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
>>>> -QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
>>>> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
>>>> +                               const char *firstname);
>>>> +QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
>>>> +                          int permit_abbrev);
>>>>    void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
>>>>                                int permit_abbrev);
>>>>    QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
>>>> diff --git a/util/qemu-option.c b/util/qemu-option.c
>>>> index 0488c27..5db6d76 100644
>>>> --- a/util/qemu-option.c
>>>> +++ b/util/qemu-option.c
>>>> @@ -33,6 +33,8 @@
>>>>    #include "qapi/qmp/qerror.h"
>>>>    #include "qemu/option_int.h"
>>>>
>>>> +static void qemu_opt_del(QemuOpt *opt);
>>>> +
>>>>    /*
>>>>     * Extracts the name of an option from the parameter string (p points at the
>>>>     * first byte of the option name)
>>>> @@ -549,6 +551,16 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
>>>      const char *qemu_opt_get(QemuOpts *opts, const char *name)
>>>      {
>>>          QemuOpt *opt = qemu_opt_find(opts, name);
>>>          const QemuOptDesc *desc;
>>>          desc = find_desc_by_name(opts->list->desc, name);
>>>
>>>          return opt ? opt->str :
>>>>            (desc && desc->def_value_str ? desc->def_value_str : NULL);
>>>>    }
>>>>
>>>> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name)
>>>> +{
>>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>>> +    const char *str = opt ? g_strdup(opt->str) : NULL;
>>>> +    if (opt) {
>>>> +        qemu_opt_del(opt);
>>>> +    }
>>>> +    return str;
>>>> +}
>>>> +
>>>
>>> Unlike qemu_opt_del(), this one doesn't use def_value_str.  Why?  Isn't
>>> that a trap for users of this function?
>>>
>>> Same question for the qemu_opt_get_FOO_del() that follow.
>
> I'm still interested in answers :)
>
Here I made a mistake, it should use def_value_str, will fix in next 
version.
>>>>    bool qemu_opt_has_help_opt(QemuOpts *opts)
>>>>    {
>>>>        QemuOpt *opt;
>>>> @@ -577,6 +589,22 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
>>>>        return opt->value.boolean;
>>>>    }
>>>>
>>>> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
>>>> +{
>>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>>> +    bool ret;
>>>> +
>>>> +    if (opt == NULL) {
>>>> +        return defval;
>>>> +    }
>>>> +    ret = opt->value.boolean;
>>>> +    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
>>>> +    if (opt) {
>>>> +        qemu_opt_del(opt);
>>>> +    }
>>>> +    return ret;
>>>> +}
>>>> +
>>>>    uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
>>>>    {
>>>>        QemuOpt *opt = qemu_opt_find(opts, name);
>>>> @@ -609,6 +637,23 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
>>>>        return opt->value.uint;
>>>>    }
>>>>
>>>> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
>>>> +                               uint64_t defval)
>>>> +{
>>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>>> +    uint64_t ret;
>>>> +
>>>> +    if (opt == NULL) {
>>>> +        return defval;
>>>> +    }
>>>> +    ret = opt->value.uint;
>>>> +    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
>>>> +    if (opt) {
>>>> +        qemu_opt_del(opt);
>>>> +    }
>>>> +    return ret;
>>>> +}
>>>> +
>>>>    static void qemu_opt_parse(QemuOpt *opt, Error **errp)
>>>>    {
>>>>        if (opt->desc == NULL)
>>>> @@ -646,7 +691,7 @@ static bool opts_accepts_any(const QemuOpts *opts)
>>>>    }
>>>>
>>>>    static void opt_set(QemuOpts *opts, const char *name, const char *value,
>>>> -                    bool prepend, Error **errp)
>>>> +                    bool prepend, bool replace, Error **errp)
>>>>    {
>>>>        QemuOpt *opt;
>>>>        const QemuOptDesc *desc;
>>>> @@ -658,6 +703,11 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>>>>            return;
>>>>        }
>>>>
>>>> +    opt = qemu_opt_find(opts, name);
>>>> +    if (replace && opt) {
>>>> +        qemu_opt_del(opt);
>>>> +    }
>>>> +
>>>>        opt = g_malloc0(sizeof(*opt));
>>>>        opt->name = g_strdup(name);
>>>>        opt->opts = opts;
>>>> @@ -667,7 +717,6 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
>>>>            QTAILQ_INSERT_TAIL(&opts->head, opt, next);
>>>>        }
>>>>        opt->desc = desc;
>>>> -    opt->str = g_strdup(value);
>>>>        opt->str = g_strdup(value ?: desc->def_value_str);
>>>>        qemu_opt_parse(opt, &local_err);
>>>>        if (error_is_set(&local_err)) {
>>>
>>> Here you plug the leak you created in PATCH 1/6.
>>>
>>>> @@ -680,7 +729,29 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
>>>>    {
>>>>        Error *local_err = NULL;
>>>>
>>>> -    opt_set(opts, name, value, false, &local_err);
>>>> +    opt_set(opts, name, value, false, false, &local_err);
>>>> +    if (error_is_set(&local_err)) {
>>>> +        qerror_report_err(local_err);
>>>> +        error_free(local_err);
>>>> +        return -1;
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +/*
>>>> + * If name exists, the function will delete the opt first and then add a new
>>>> + * one.
>>>> + */
>>>> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char *value)
>>>> +{
>>>> +    Error *local_err = NULL;
>>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>>> +
>>>> +    if (opt) {
>>>> +        qemu_opt_del(opt);
>>>> +    }
>>>
>>> Why?  Won't opt_set() delete it already?
>>>
>> No, opt_set will not delete it, but add a new opt. In block layer,
>
> Then I'm confused...
>
>> while parsing options, if the parameter is parsed, it should be
>> deleted and won't be used again, so I delete it manually.
>>
>>> Same question for the qemu_opt_replace_set_FOO() that follow.
>>>
>>>> +    opt_set(opts, name, value, false, true, &local_err);
>
> ... because here you pass true for parameter replace, which I (naively?)
> expect to delete the option.  Can you unconfuse me?
>

Sorry, I used qemu_opt_del twice, will clean.

>>>>        if (error_is_set(&local_err)) {
>>>>            qerror_report_err(local_err);
>>>>            error_free(local_err);
>>>> @@ -693,7 +764,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
>>>>    void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>>>>                          Error **errp)
>>>>    {
>>>> -    opt_set(opts, name, value, false, errp);
>>>> +    opt_set(opts, name, value, false, false, errp);
>>>>    }
>>>>
>>>>    int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
>>>> @@ -740,6 +811,16 @@ int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val)
>>>>        return 0;
>>>>    }
>>>>
>>>> +int qemu_opt_replace_set_number(QemuOpts *opts, const char *name, int64_t val)
>>>> +{
>>>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>>>> +
>>>> +    if (opt) {
>>>> +        qemu_opt_del(opt);
>>>> +    }
>>>> +    return qemu_opt_set_number(opts, name, val);
>>>> +}
>>>> +
>>>>    int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
>>>>                         int abort_on_failure)
>>>>    {
>>>> @@ -917,7 +998,7 @@ int qemu_opts_print(QemuOpts *opts)
>>>>    }
>>>>
>>>>    static int opts_do_parse(QemuOpts *opts, const char *params,
>>>> -                         const char *firstname, bool prepend)
>>>> +                         const char *firstname, bool prepend, bool replace)
>>>>    {
>>>>        char option[128], value[1024];
>>>>        const char *p,*pe,*pc;
>>>> @@ -953,7 +1034,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
>>>>            }
>>>>            if (strcmp(option, "id") != 0) {
>>>>                /* store and parse */
>>>> -            opt_set(opts, option, value, prepend, &local_err);
>>>> +            opt_set(opts, option, value, prepend, replace, &local_err);
>>>>                if (error_is_set(&local_err)) {
>>>>                    qerror_report_err(local_err);
>>>>                    error_free(local_err);
>>>> @@ -969,7 +1050,13 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
>>>>
>>>>    int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
>>>>    {
>>>> -    return opts_do_parse(opts, params, firstname, false);
>>>> +    return opts_do_parse(opts, params, firstname, false, false);
>>>> +}
>>>> +
>>>> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
>>>> +                               const char *firstname)
>>>> +{
>>>> +    return opts_do_parse(opts, params, firstname, false, true);
>>>>    }
>>>>
>>>>    static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>>>> @@ -1008,7 +1095,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>>>>            return NULL;
>>>>        }
>>>>
>>>> -    if (opts_do_parse(opts, params, firstname, defaults) != 0) {
>>>> +    if (opts_do_parse(opts, params, firstname, defaults, false) != 0) {
>>>>            qemu_opts_del(opts);
>>>>            return NULL;
>>>>        }
>>>
>>>
>
>
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2013-05-07  7:54 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-10  6:25 [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 1/6] add def_value_str in QemuOptDesc struct and rewrite qemu_opts_print Dong Xu Wang
2013-05-06 12:16   ` Markus Armbruster
2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 2/6] avoid duplication of default value in QemuOpts Dong Xu Wang
2013-05-06 11:54   ` Markus Armbruster
2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 3/6] Create four QemuOptsList related functions Dong Xu Wang
2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 4/6] create some QemuOpts functons Dong Xu Wang
2013-05-06 12:20   ` Markus Armbruster
2013-05-07  5:19     ` Dong Xu Wang
2013-05-07  7:38       ` Markus Armbruster
2013-05-07  7:53         ` Dong Xu Wang
2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 5/6] Use QemuOpts support in block layer Dong Xu Wang
2013-04-10  6:25 ` [Qemu-devel] [PATCH V13 6/6] remove QEMUOptionParameter related functions and struct Dong Xu Wang
2013-04-22  2:20 ` [Qemu-devel] [PATCH V13 0/6] replace QEMUOptionParameter with QemuOpts parser Dong Xu Wang
2013-04-22  8:18   ` Markus Armbruster
2013-05-06 12:26 ` Markus Armbruster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.