All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig
@ 2020-11-11 14:25 Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 01/12] tests: convert check-qom-proplist to keyval Paolo Bonzini
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

This is yet another RFC on the command-line parsing overhaul.  Here,
I'm switching HMP, -object and -readconfig away from QemuOpts.  There are
pending QemuOpts and keyval patches that make the syntaxes the same
apart from:

- "implicit value" options (where the lack of value is turned
into "on" or "off"), which will be deprecated

- the processing of invalid, empty or overlong keys which can be considered
bugfixes.

Along the way, the object_add HMP command grows help support.

The plan on top of this is to also keyval-ify -M and -accel.  The reason
for this, in my evil plan, is to allow for compound properties.  These
compound properties would be used for replacements of options like -smp
(-M smp.xxx), -icount (-accel tcg,icount.xxx) and -chardev (as in -object
chardev-socket,addr.host).

Paolo

Paolo Bonzini (12):
  tests: convert check-qom-proplist to keyval
  keyval: introduce keyval_parse_into
  hmp: replace "O" parser with keyval
  qom: use qemu_printf to print help for user-creatable objects
  hmp: special case help options for object_add
  qemu-io: use keyval for -object parsing
  qemu-nbd: use keyval for -object parsing
  qemu-img: use keyval for -object parsing
  qemu-config: add error propagation to qemu_config_parse
  qemu-config: parse configuration files to a QDict
  qemu-option: support accept-any QemuOptsList in qemu_opts_absorb_qdict
  qemu: use keyval for -object parsing

 block/blkdebug.c                |   3 +-
 hmp-commands.hx                 |   6 +-
 include/qemu/config-file.h      |   8 +-
 include/qemu/option.h           |   2 +
 include/qom/object_interfaces.h |  45 +-----
 monitor/hmp-cmds.c              |  22 +--
 monitor/hmp.c                   |  20 ++-
 qemu-img.c                      | 258 +++++++-------------------------
 qemu-io.c                       |  42 ++----
 qemu-nbd.c                      |  42 ++----
 qom/object_interfaces.c         |  57 +------
 softmmu/vl.c                    | 113 ++++++++------
 tests/check-qom-proplist.c      |  58 ++++---
 util/keyval.c                   |  39 ++++-
 util/qemu-config.c              |  99 +++++++-----
 util/qemu-option.c              |   3 +-
 16 files changed, 324 insertions(+), 493 deletions(-)

-- 
2.26.2



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

* [PATCH 01/12] tests: convert check-qom-proplist to keyval
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 02/12] keyval: introduce keyval_parse_into Paolo Bonzini
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

The command-line creation test is using QemuOpts.  Switch it to keyval,
since all the -object command line options will follow
qemu-storage-daemon and do the same.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/check-qom-proplist.c | 58 +++++++++++++++++++++++++-------------
 1 file changed, 38 insertions(+), 20 deletions(-)

diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index 1b76581980..8dba26fb3c 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -21,6 +21,8 @@
 #include "qemu/osdep.h"
 
 #include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qobject.h"
 #include "qom/object.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
@@ -400,42 +402,58 @@ static void test_dummy_createlist(void)
 
 static void test_dummy_createcmdl(void)
 {
-    QemuOpts *opts;
+    QDict *qdict;
     DummyObject *dobj;
     Error *err = NULL;
+    bool help;
     const char *params = TYPE_DUMMY \
                          ",id=dev0," \
                          "bv=yes,sv=Hiss hiss hiss,av=platypus";
 
-    qemu_add_opts(&qemu_object_opts);
-    opts = qemu_opts_parse(&qemu_object_opts, params, true, &err);
+    qdict = keyval_parse(params, "qom-type", &help, &err);
     g_assert(err == NULL);
-    g_assert(opts);
+    g_assert(qdict);
+    g_assert(!help);
 
-    dobj = DUMMY_OBJECT(user_creatable_add_opts(opts, &err));
+    g_assert(user_creatable_add_dict(qdict, true, &err));
     g_assert(err == NULL);
+    qobject_unref(qdict);
+
+    dobj = DUMMY_OBJECT(object_resolve_path_component(object_get_objects_root(),
+                                                      "dev0"));
     g_assert(dobj);
     g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
     g_assert(dobj->bv == true);
     g_assert(dobj->av == DUMMY_PLATYPUS);
 
+    qdict = keyval_parse(params, "qom-type", &help, &err);
+    g_assert(!user_creatable_add_dict(qdict, true, &err));
+    g_assert(err);
+    g_assert(object_resolve_path_component(object_get_objects_root(), "dev0")
+             == OBJECT(dobj));
+    qobject_unref(qdict);
+    error_free(err);
+    err = NULL;
+
+    qdict = keyval_parse(params, "qom-type", &help, &err);
     user_creatable_del("dev0", &error_abort);
+    g_assert(object_resolve_path_component(object_get_objects_root(), "dev0")
+             == NULL);
 
-    object_unref(OBJECT(dobj));
-
-    /*
-     * cmdline-parsing via qemu_opts_parse() results in a QemuOpts entry
-     * corresponding to the Object's ID to be added to the QemuOptsList
-     * for objects. To avoid having this entry conflict with future
-     * Objects using the same ID (which can happen in cases where
-     * qemu_opts_parse() is used to parse the object params, such as
-     * with hmp_object_add() at the time of this comment), we need to
-     * check for this in user_creatable_del() and remove the QemuOpts if
-     * it is present.
-     *
-     * The below check ensures this works as expected.
-     */
-    g_assert_null(qemu_opts_find(&qemu_object_opts, "dev0"));
+    g_assert(user_creatable_add_dict(qdict, true, &err));
+    g_assert(err == NULL);
+    qobject_unref(qdict);
+
+    dobj = DUMMY_OBJECT(object_resolve_path_component(object_get_objects_root(),
+                                                      "dev0"));
+    g_assert(dobj);
+    g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
+    g_assert(dobj->bv == true);
+    g_assert(dobj->av == DUMMY_PLATYPUS);
+    g_assert(object_resolve_path_component(object_get_objects_root(), "dev0")
+             == OBJECT(dobj));
+
+    object_unparent(OBJECT(dobj));
 }
 
 static void test_dummy_badenum(void)
-- 
2.26.2




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

* [PATCH 02/12] keyval: introduce keyval_parse_into
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 01/12] tests: convert check-qom-proplist to keyval Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 03/12] hmp: replace "O" parser with keyval Paolo Bonzini
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Allow parsing multiple keyval sequences into the same dictionary (as will
become useful for -M) or simply allow using a dictionary that came from
somewhere else (e.g. in an HMP parsing handler).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/qemu/option.h |  2 ++
 util/keyval.c         | 39 ++++++++++++++++++++++++++++++++-------
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index f73e0dc7d9..092e291c37 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -147,6 +147,8 @@ void qemu_opts_print_help(QemuOptsList *list, bool print_caption);
 void qemu_opts_free(QemuOptsList *list);
 QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
 
+QDict *keyval_parse_into(QDict *qdict, const char *params, const char *implied_key,
+                         bool *p_help, Error **errp);
 QDict *keyval_parse(const char *params, const char *implied_key,
                     bool *help, Error **errp);
 
diff --git a/util/keyval.c b/util/keyval.c
index 76daab0885..dd93da1ce5 100644
--- a/util/keyval.c
+++ b/util/keyval.c
@@ -436,13 +436,12 @@ static QObject *keyval_listify(QDict *cur, GSList *key_of_cur, Error **errp)
  * If @p_help is not NULL, store whether help is requested there.
  * If @p_help is NULL and help is requested, fail.
  *
- * On success, return a dictionary of the parsed keys and values.
+ * On success, return @dict, now filled with the parsed keys and values.
  * On failure, store an error through @errp and return NULL.
  */
-QDict *keyval_parse(const char *params, const char *implied_key,
-                    bool *p_help, Error **errp)
+QDict *keyval_parse_into(QDict *qdict, const char *params, const char *implied_key,
+                         bool *p_help, Error **errp)
 {
-    QDict *qdict = qdict_new();
     QObject *listified;
     g_autofree char *dup;
     char *s;
@@ -452,7 +451,6 @@ QDict *keyval_parse(const char *params, const char *implied_key,
     while (*s) {
         s = keyval_parse_one(qdict, s, implied_key, &help, errp);
         if (!s) {
-            qobject_unref(qdict);
             return NULL;
         }
         implied_key = NULL;
@@ -462,15 +460,42 @@ QDict *keyval_parse(const char *params, const char *implied_key,
         *p_help = help;
     } else if (help) {
         error_setg(errp, "Help is not available for this option");
-        qobject_unref(qdict);
         return NULL;
     }
 
     listified = keyval_listify(qdict, NULL, errp);
     if (!listified) {
-        qobject_unref(qdict);
         return NULL;
     }
     assert(listified == QOBJECT(qdict));
     return qdict;
 }
+
+/*
+ * Parse @params in QEMU's traditional KEY=VALUE,... syntax.
+ *
+ * If @implied_key, the first KEY= can be omitted.  @implied_key is
+ * implied then, and VALUE can't be empty or contain ',' or '='.
+ *
+ * A parameter "help" or "?" without a value isn't added to the
+ * resulting dictionary, but instead is interpreted as help request.
+ * All other options are parsed and returned normally so that context
+ * specific help can be printed.
+ *
+ * If @p_help is not NULL, store whether help is requested there.
+ * If @p_help is NULL and help is requested, fail.
+ *
+ * On success, return a dictionary of the parsed keys and values.
+ * On failure, store an error through @errp and return NULL.
+ */
+QDict *keyval_parse(const char *params, const char *implied_key,
+                    bool *p_help, Error **errp)
+{
+    QDict *qdict = qdict_new();
+    QDict *ret = keyval_parse_into(qdict, params, implied_key, p_help, errp);
+
+    if (!ret) {
+        qobject_unref(qdict);
+    }
+    return ret;
+}
-- 
2.26.2




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

* [PATCH 03/12] hmp: replace "O" parser with keyval
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 01/12] tests: convert check-qom-proplist to keyval Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 02/12] keyval: introduce keyval_parse_into Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 04/12] qom: use qemu_printf to print help for user-creatable objects Paolo Bonzini
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

HMP is using QemuOpts to parse free-form commands device_add,
netdev_add and object_add.  However, none of these need QemuOpts
for validation (these three QemuOptsLists are all of the catch-all
kind), and keyval is already able to parse into QDict.  So use
keyval directly, avoiding the detour from
string to QemuOpts to QDict.

The args_type now stores the implied key.  This arguably makes more
sense than storing the QemuOptsList name; at least, it _is_ a key
that might end up in the arguments QDict.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hmp-commands.hx |  6 +++---
 monitor/hmp.c   | 20 +++++++++-----------
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index ff2d7aa8f3..35ecd0d9ca 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -668,7 +668,7 @@ ERST
 
     {
         .name       = "device_add",
-        .args_type  = "device:O",
+        .args_type  = "driver:O",
         .params     = "driver[,prop=value][,...]",
         .help       = "add device, like -device on the command line",
         .cmd        = hmp_device_add,
@@ -1314,7 +1314,7 @@ ERST
 
     {
         .name       = "netdev_add",
-        .args_type  = "netdev:O",
+        .args_type  = "type:O",
         .params     = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user],id=str[,prop=value][,...]",
         .help       = "add host network device",
         .cmd        = hmp_netdev_add,
@@ -1342,7 +1342,7 @@ ERST
 
     {
         .name       = "object_add",
-        .args_type  = "object:O",
+        .args_type  = "qom-type:O",
         .params     = "[qom-type=]type,id=str[,prop=value][,...]",
         .help       = "create QOM object",
         .cmd        = hmp_object_add,
diff --git a/monitor/hmp.c b/monitor/hmp.c
index 0027f1465d..e535baafd0 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -744,13 +744,9 @@ static QDict *monitor_parse_arguments(Monitor *mon,
             break;
         case 'O':
             {
-                QemuOptsList *opts_list;
-                QemuOpts *opts;
+                Error *errp;
+                bool help;
 
-                opts_list = qemu_find_opts(key);
-                if (!opts_list || opts_list->desc->name) {
-                    goto bad_type;
-                }
                 while (qemu_isspace(*p)) {
                     p++;
                 }
@@ -760,12 +756,14 @@ static QDict *monitor_parse_arguments(Monitor *mon,
                 if (get_str(buf, sizeof(buf), &p) < 0) {
                     goto fail;
                 }
-                opts = qemu_opts_parse_noisily(opts_list, buf, true);
-                if (!opts) {
-                    goto fail;
+                keyval_parse_into(qdict, buf, key, &help, &errp);
+                if (help) {
+                    if (qdict_haskey(qdict, key)) {
+                        qdict_put_bool(qdict, "help", true);
+                    } else {
+                        qdict_put_str(qdict, key, "help");
+                    }
                 }
-                qemu_opts_to_qdict(opts, qdict);
-                qemu_opts_del(opts);
             }
             break;
         case '/':
-- 
2.26.2




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

* [PATCH 04/12] qom: use qemu_printf to print help for user-creatable objects
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (2 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 03/12] hmp: replace "O" parser with keyval Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 05/12] hmp: special case help options for object_add Paolo Bonzini
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

This is needed when we add help support for object_add.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qom/object_interfaces.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index ed896fe764..34edc3d1d8 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -13,6 +13,7 @@
 #include "qemu/option.h"
 #include "qapi/opts-visitor.h"
 #include "qemu/config-file.h"
+#include "qemu/qemu-print.h"
 
 bool user_creatable_complete(UserCreatable *uc, Error **errp)
 {
@@ -214,15 +215,15 @@ char *object_property_help(const char *name, const char *type,
     return g_string_free(str, false);
 }
 
-static void user_creatable_print_types(void)
+void user_creatable_print_types(void)
 {
     GSList *l, *list;
 
-    printf("List of user creatable objects:\n");
+    qemu_printf("List of user creatable objects:\n");
     list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
     for (l = list; l != NULL; l = l->next) {
         ObjectClass *oc = OBJECT_CLASS(l->data);
-        printf("  %s\n", object_class_get_name(oc));
+        qemu_printf("  %s\n", object_class_get_name(oc));
     }
     g_slist_free(list);
 }
@@ -253,12 +254,12 @@ static bool user_creatable_print_type_properites(const char *type)
     }
     g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
     if (array->len > 0) {
-        printf("%s options:\n", type);
+        qemu_printf("%s options:\n", type);
     } else {
-        printf("There are no options for %s.\n", type);
+        qemu_printf("There are no options for %s.\n", type);
     }
     for (i = 0; i < array->len; i++) {
-        printf("%s\n", (char *)array->pdata[i]);
+        qemu_printf("%s\n", (char *)array->pdata[i]);
     }
     g_ptr_array_set_free_func(array, g_free);
     g_ptr_array_free(array, true);
-- 
2.26.2




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

* [PATCH 05/12] hmp: special case help options for object_add
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (3 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 04/12] qom: use qemu_printf to print help for user-creatable objects Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 06/12] qemu-io: use keyval for -object parsing Paolo Bonzini
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Fix "object_add help" and "object_add TYPE,help".

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/qom/object_interfaces.h |  9 ++++++++-
 monitor/hmp-cmds.c              | 22 ++++++++--------------
 qom/object_interfaces.c         |  2 +-
 3 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
index 07d5cc8832..abb23eaea3 100644
--- a/include/qom/object_interfaces.h
+++ b/include/qom/object_interfaces.h
@@ -149,6 +149,13 @@ typedef bool (*user_creatable_add_opts_predicate)(const char *type);
 int user_creatable_add_opts_foreach(void *opaque,
                                     QemuOpts *opts, Error **errp);
 
+/**
+ * user_creatable_print_types:
+ *
+ * Prints a list of user-creatable objects to stdout or the monitor.
+ */
+void user_creatable_print_types(void);
+
 /**
  * user_creatable_print_help:
  * @type: the QOM type to be added
@@ -174,7 +181,7 @@ bool user_creatable_print_help(const char *type, QemuOpts *opts);
  * no help was requested. It should only be called if we know that help is
  * requested and it will always print some help.
  */
-void user_creatable_print_help_from_qdict(QDict *args);
+void user_creatable_print_help_from_qdict(const QDict *args);
 
 /**
  * user_creatable_del:
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 65d8ff4849..153ece8176 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -1664,23 +1664,17 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)
 void hmp_object_add(Monitor *mon, const QDict *qdict)
 {
     Error *err = NULL;
-    QemuOpts *opts;
-    Object *obj = NULL;
 
-    opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err);
-    if (err) {
-        goto end;
+    if (is_help_option(qdict_get_str(qdict, "qom-type"))) {
+        user_creatable_print_types();
+        return;
     }
-
-    obj = user_creatable_add_opts(opts, &err);
-    qemu_opts_del(opts);
-
-end:
-    hmp_handle_error(mon, err);
-
-    if (obj) {
-        object_unref(obj);
+    if (qdict_haskey(qdict, "help")) {
+        user_creatable_print_help_from_qdict(qdict);
+        return;
     }
+    user_creatable_add_dict((QDict *)qdict, true, &err);
+    hmp_handle_error(mon, err);
 }
 
 void hmp_getfd(Monitor *mon, const QDict *qdict)
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index 34edc3d1d8..f7dcdf18e2 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -280,7 +280,7 @@ bool user_creatable_print_help(const char *type, QemuOpts *opts)
     return false;
 }
 
-void user_creatable_print_help_from_qdict(QDict *args)
+void user_creatable_print_help_from_qdict(const QDict *args)
 {
     const char *type = qdict_get_try_str(args, "qom-type");
 
-- 
2.26.2




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

* [PATCH 06/12] qemu-io: use keyval for -object parsing
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (4 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 05/12] hmp: special case help options for object_add Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 07/12] qemu-nbd: " Paolo Bonzini
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Enable creation of object with non-scalar properties.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-io.c | 42 +++++++++++++-----------------------------
 1 file changed, 13 insertions(+), 29 deletions(-)

diff --git a/qemu-io.c b/qemu-io.c
index ac88d8bd40..306086f767 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -477,23 +477,6 @@ enum {
     OPTION_IMAGE_OPTS = 257,
 };
 
-static QemuOptsList qemu_object_opts = {
-    .name = "object",
-    .implied_opt_name = "qom-type",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
-    .desc = {
-        { }
-    },
-};
-
-static bool qemu_io_object_print_help(const char *type, QemuOpts *opts)
-{
-    if (user_creatable_print_help(type, opts)) {
-        exit(0);
-    }
-    return true;
-}
-
 static QemuOptsList file_opts = {
     .name = "file",
     .implied_opt_name = "file",
@@ -550,7 +533,6 @@ int main(int argc, char **argv)
     qcrypto_init(&error_fatal);
 
     module_call_init(MODULE_INIT_QOM);
-    qemu_add_opts(&qemu_object_opts);
     qemu_add_opts(&qemu_trace_opts);
     bdrv_init();
 
@@ -612,14 +594,20 @@ int main(int argc, char **argv)
         case 'U':
             force_share = true;
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *qopts;
-            qopts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                            optarg, true);
-            if (!qopts) {
-                exit(1);
+        case OPTION_OBJECT:
+            {
+                QDict *args;
+                bool help;
+
+                args = keyval_parse(optarg, "qom-type", &help, &error_fatal);
+                if (help) {
+                    user_creatable_print_help_from_qdict(args);
+                    exit(EXIT_SUCCESS);
+                }
+                user_creatable_add_dict(args, true, &error_fatal);
+                qobject_unref(args);
+                break;
             }
-        }   break;
         case OPTION_IMAGE_OPTS:
             imageOpts = true;
             break;
@@ -644,10 +632,6 @@ int main(int argc, char **argv)
         exit(1);
     }
 
-    qemu_opts_foreach(&qemu_object_opts,
-                      user_creatable_add_opts_foreach,
-                      qemu_io_object_print_help, &error_fatal);
-
     if (!trace_init_backends()) {
         exit(1);
     }
-- 
2.26.2




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

* [PATCH 07/12] qemu-nbd: use keyval for -object parsing
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (5 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 06/12] qemu-io: use keyval for -object parsing Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 08/12] qemu-img: " Paolo Bonzini
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Enable creation of object with non-scalar properties.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-nbd.c | 42 +++++++++++++-----------------------------
 1 file changed, 13 insertions(+), 29 deletions(-)

diff --git a/qemu-nbd.c b/qemu-nbd.c
index a7075c5419..b4bd21a21e 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -407,23 +407,6 @@ static QemuOptsList file_opts = {
     },
 };
 
-static QemuOptsList qemu_object_opts = {
-    .name = "object",
-    .implied_opt_name = "qom-type",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
-    .desc = {
-        { }
-    },
-};
-
-static bool qemu_nbd_object_print_help(const char *type, QemuOpts *opts)
-{
-    if (user_creatable_print_help(type, opts)) {
-        exit(0);
-    }
-    return true;
-}
-
 
 static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, bool list,
                                           Error **errp)
@@ -599,7 +582,6 @@ int main(int argc, char **argv)
     qcrypto_init(&error_fatal);
 
     module_call_init(MODULE_INIT_QOM);
-    qemu_add_opts(&qemu_object_opts);
     qemu_add_opts(&qemu_trace_opts);
     qemu_init_exec_dir(argv[0]);
 
@@ -752,14 +734,20 @@ int main(int argc, char **argv)
         case '?':
             error_report("Try `%s --help' for more information.", argv[0]);
             exit(EXIT_FAILURE);
-        case QEMU_NBD_OPT_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                exit(EXIT_FAILURE);
+        case QEMU_NBD_OPT_OBJECT:
+            {
+                QDict *args;
+                bool help;
+
+                args = keyval_parse(optarg, "qom-type", &help, &error_fatal);
+                if (help) {
+                    user_creatable_print_help_from_qdict(args);
+                    exit(EXIT_SUCCESS);
+                }
+                user_creatable_add_dict(args, true, &error_fatal);
+                qobject_unref(args);
+                break;
             }
-        }   break;
         case QEMU_NBD_OPT_TLSCREDS:
             tlscredsid = optarg;
             break;
@@ -807,10 +795,6 @@ int main(int argc, char **argv)
         export_name = "";
     }
 
-    qemu_opts_foreach(&qemu_object_opts,
-                      user_creatable_add_opts_foreach,
-                      qemu_nbd_object_print_help, &error_fatal);
-
     if (!trace_init_backends()) {
         exit(1);
     }
-- 
2.26.2




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

* [PATCH 08/12] qemu-img: use keyval for -object parsing
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (6 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 07/12] qemu-nbd: " Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 09/12] qemu-config: add error propagation to qemu_config_parse Paolo Bonzini
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Enable creation of object with non-scalar properties.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-img.c | 258 +++++++++++------------------------------------------
 1 file changed, 52 insertions(+), 206 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 8bdea40b58..a91bbba4c6 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -227,21 +227,27 @@ static void QEMU_NORETURN help(void)
     exit(EXIT_SUCCESS);
 }
 
-static QemuOptsList qemu_object_opts = {
-    .name = "object",
-    .implied_opt_name = "qom-type",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
-    .desc = {
-        { }
-    },
-};
-
-static bool qemu_img_object_print_help(const char *type, QemuOpts *opts)
+static void qemu_img_object_parse(const char *optarg, int exit_code)
 {
-    if (user_creatable_print_help(type, opts)) {
-        exit(0);
+    QDict *args;
+    bool help;
+    Error *local_error = NULL;
+
+    args = keyval_parse(optarg, "qom-type", &help, &local_error);
+    if (local_error) {
+        error_report_err(local_error);
+        exit(exit_code);
     }
-    return true;
+    if (help) {
+        user_creatable_print_help_from_qdict(args);
+        exit(EXIT_SUCCESS);
+    }
+    user_creatable_add_dict(args, true, &local_error);
+    if (local_error) {
+        error_report_err(local_error);
+        exit(exit_code);
+    }
+    qobject_unref(args);
 }
 
 /*
@@ -567,14 +573,9 @@ static int img_create(int argc, char **argv)
         case 'u':
             flags |= BDRV_O_NO_BACKING;
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                goto fail;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
+            break;
         }
     }
 
@@ -590,12 +591,6 @@ static int img_create(int argc, char **argv)
     }
     optind++;
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        goto fail;
-    }
-
     /* Get image size, if specified */
     if (optind < argc) {
         int64_t sval;
@@ -805,14 +800,9 @@ static int img_check(int argc, char **argv)
         case 'U':
             force_share = true;
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                return 1;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -832,12 +822,6 @@ static int img_check(int argc, char **argv)
         return 1;
     }
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        return 1;
-    }
-
     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
     if (ret < 0) {
         error_report("Invalid source cache option: %s", cache);
@@ -1035,14 +1019,9 @@ static int img_commit(int argc, char **argv)
                 return 1;
             }
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                return 1;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -1059,12 +1038,6 @@ static int img_commit(int argc, char **argv)
     }
     filename = argv[optind++];
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        return 1;
-    }
-
     flags = BDRV_O_RDWR | BDRV_O_UNMAP;
     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
     if (ret < 0) {
@@ -1424,15 +1397,9 @@ static int img_compare(int argc, char **argv)
         case 'U':
             force_share = true;
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                ret = 2;
-                goto out4;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 2);
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -1451,13 +1418,6 @@ static int img_compare(int argc, char **argv)
     filename1 = argv[optind++];
     filename2 = argv[optind++];
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        ret = 2;
-        goto out4;
-    }
-
     /* Initialize before goto out */
     qemu_progress_init(progress, 2.0);
 
@@ -1642,7 +1602,6 @@ out2:
     blk_unref(blk1);
 out3:
     qemu_progress_end();
-out4:
     return ret;
 }
 
@@ -2344,15 +2303,9 @@ static int img_convert(int argc, char **argv)
                 goto fail_getopt;
             }
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *object_opts;
-            object_opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                                  optarg, true);
-            if (!object_opts) {
-                goto fail_getopt;
-            }
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
             break;
-        }
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -2380,12 +2333,6 @@ static int img_convert(int argc, char **argv)
         out_fmt = "raw";
     }
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        goto fail_getopt;
-    }
-
     if (s.compressed && s.copy_range) {
         error_report("Cannot enable copy offloading when -c is used");
         goto fail_getopt;
@@ -2977,14 +2924,9 @@ static int img_info(int argc, char **argv)
         case OPTION_BACKING_CHAIN:
             chain = true;
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                return 1;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -3004,12 +2946,6 @@ static int img_info(int argc, char **argv)
         return 1;
     }
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        return 1;
-    }
-
     list = collect_image_info_list(image_opts, filename, fmt, chain,
                                    force_share);
     if (!list) {
@@ -3219,14 +3155,9 @@ static int img_map(int argc, char **argv)
                 return 1;
             }
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                return 1;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -3246,12 +3177,6 @@ static int img_map(int argc, char **argv)
         return 1;
     }
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        return 1;
-    }
-
     blk = img_open(image_opts, filename, fmt, 0, false, false, force_share);
     if (!blk) {
         return 1;
@@ -3390,14 +3315,9 @@ static int img_snapshot(int argc, char **argv)
         case 'U':
             force_share = true;
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                return 1;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -3409,12 +3329,6 @@ static int img_snapshot(int argc, char **argv)
     }
     filename = argv[optind++];
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        return 1;
-    }
-
     /* Open the image */
     blk = img_open(image_opts, filename, NULL, bdrv_oflags, false, quiet,
                    force_share);
@@ -3548,14 +3462,9 @@ static int img_rebase(int argc, char **argv)
         case 'q':
             quiet = true;
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                return 1;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -3577,12 +3486,6 @@ static int img_rebase(int argc, char **argv)
     }
     filename = argv[optind++];
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        return 1;
-    }
-
     qemu_progress_init(progress, 2.0);
     qemu_progress_print(0, 100);
 
@@ -3973,14 +3876,9 @@ static int img_resize(int argc, char **argv)
         case 'q':
             quiet = true;
             break;
-        case OPTION_OBJECT: {
-            QemuOpts *opts;
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                return 1;
-            }
-        }   break;
+        case OPTION_OBJECT:
+            qemu_img_object_parse(optarg, 1);
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -4002,12 +3900,6 @@ static int img_resize(int argc, char **argv)
     }
     filename = argv[optind++];
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        return 1;
-    }
-
     /* Choose grow, shrink, or absolute resize mode */
     switch (size[0]) {
     case '+':
@@ -4187,12 +4079,7 @@ static int img_amend(int argc, char **argv)
             quiet = true;
             break;
         case OPTION_OBJECT:
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
-                ret = -1;
-                goto out_no_progress;
-            }
+            qemu_img_object_parse(optarg, 1);
             break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
@@ -4207,13 +4094,6 @@ static int img_amend(int argc, char **argv)
         error_exit("Must specify options (-o)");
     }
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        ret = -1;
-        goto out_no_progress;
-    }
-
     if (quiet) {
         progress = false;
     }
@@ -4672,7 +4552,6 @@ static int img_bitmap(int argc, char **argv)
 {
     Error *err = NULL;
     int c, ret = 1;
-    QemuOpts *opts = NULL;
     const char *fmt = NULL, *src_fmt = NULL, *src_filename = NULL;
     const char *filename, *bitmap;
     BlockBackend *blk = NULL, *src = NULL;
@@ -4766,10 +4645,7 @@ static int img_bitmap(int argc, char **argv)
             merge = true;
             break;
         case OPTION_OBJECT:
-            opts = qemu_opts_parse_noisily(&qemu_object_opts, optarg, true);
-            if (!opts) {
-                goto out;
-            }
+            qemu_img_object_parse(optarg, 1);
             break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
@@ -4777,12 +4653,6 @@ static int img_bitmap(int argc, char **argv)
         }
     }
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        goto out;
-    }
-
     if (QSIMPLEQ_EMPTY(&actions)) {
         error_report("Need at least one of --add, --remove, --clear, "
                      "--enable, --disable, or --merge");
@@ -4878,7 +4748,6 @@ static int img_bitmap(int argc, char **argv)
  out:
     blk_unref(src);
     blk_unref(blk);
-    qemu_opts_del(opts);
     return ret;
 }
 
@@ -5040,10 +4909,7 @@ static int img_dd(int argc, char **argv)
             force_share = true;
             break;
         case OPTION_OBJECT:
-            if (!qemu_opts_parse_noisily(&qemu_object_opts, optarg, true)) {
-                ret = -1;
-                goto out;
-            }
+            qemu_img_object_parse(optarg, 1);
             break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
@@ -5090,13 +4956,6 @@ static int img_dd(int argc, char **argv)
         goto out;
     }
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        ret = -1;
-        goto out;
-    }
-
     blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
                     force_share);
 
@@ -5272,7 +5131,6 @@ static int img_measure(int argc, char **argv)
     char *snapshot_name = NULL;
     bool force_share = false;
     QemuOpts *opts = NULL;
-    QemuOpts *object_opts = NULL;
     QemuOpts *sn_opts = NULL;
     QemuOptsList *create_opts = NULL;
     bool image_opts = false;
@@ -5317,11 +5175,7 @@ static int img_measure(int argc, char **argv)
             force_share = true;
             break;
         case OPTION_OBJECT:
-            object_opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                                  optarg, true);
-            if (!object_opts) {
-                goto out;
-            }
+            qemu_img_object_parse(optarg, 1);
             break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
@@ -5351,12 +5205,6 @@ static int img_measure(int argc, char **argv)
         }
     }
 
-    if (qemu_opts_foreach(&qemu_object_opts,
-                          user_creatable_add_opts_foreach,
-                          qemu_img_object_print_help, &error_fatal)) {
-        goto out;
-    }
-
     if (argc - optind > 1) {
         error_report("At most one filename argument is allowed.");
         goto out;
@@ -5444,7 +5292,6 @@ static int img_measure(int argc, char **argv)
 
 out:
     qapi_free_BlockMeasureInfo(info);
-    qemu_opts_del(object_opts);
     qemu_opts_del(opts);
     qemu_opts_del(sn_opts);
     qemu_opts_free(create_opts);
@@ -5496,7 +5343,6 @@ int main(int argc, char **argv)
         error_exit("Not enough arguments");
     }
 
-    qemu_add_opts(&qemu_object_opts);
     qemu_add_opts(&qemu_source_opts);
     qemu_add_opts(&qemu_trace_opts);
 
-- 
2.26.2




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

* [PATCH 09/12] qemu-config: add error propagation to qemu_config_parse
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (7 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 08/12] qemu-img: " Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 10/12] qemu-option: support accept-any QemuOptsList in qemu_opts_absorb_qdict Paolo Bonzini
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

This enables some simplification of vl.c via error_fatal.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/blkdebug.c           |  3 +--
 include/qemu/config-file.h |  4 ++--
 softmmu/vl.c               | 24 +++++++-----------------
 util/qemu-config.c         | 20 ++++++++++----------
 4 files changed, 20 insertions(+), 31 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index 5fe6172da9..7eaa8a28bf 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -279,9 +279,8 @@ static int read_config(BDRVBlkdebugState *s, const char *filename,
             return -errno;
         }
 
-        ret = qemu_config_parse(f, config_groups, filename);
+        ret = qemu_config_parse(f, config_groups, filename, errp);
         if (ret < 0) {
-            error_setg(errp, "Could not parse blkdebug config file");
             goto fail;
         }
     }
diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
index 29226107bd..4e235f63ce 100644
--- a/include/qemu/config-file.h
+++ b/include/qemu/config-file.h
@@ -11,9 +11,9 @@ void qemu_add_drive_opts(QemuOptsList *list);
 int qemu_global_option(const char *str);
 
 void qemu_config_write(FILE *fp);
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname);
+int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp);
 
-int qemu_read_config_file(const char *filename);
+int qemu_read_config_file(const char *filename, Error **errp);
 
 /* Parse QDict options as a replacement for a config file (allowing multiple
    enumerated (0..(n-1)) configuration "sections") */
diff --git a/softmmu/vl.c b/softmmu/vl.c
index ac6fec732e..e46f286ad2 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2041,17 +2041,16 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
     return 0;
 }
 
-static int qemu_read_default_config_file(void)
+static void qemu_read_default_config_file(Error **errp)
 {
     int ret;
+    Error *local_err = NULL;
     g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
 
-    ret = qemu_read_config_file(file);
+    ret = qemu_read_config_file(file, &local_err);
     if (ret < 0 && ret != -ENOENT) {
-        return ret;
+        error_propagate(errp, local_err);
     }
-
-    return 0;
 }
 
 static void user_register_global_props(void)
@@ -2598,9 +2597,7 @@ void qemu_init(int argc, char **argv, char **envp)
     }
 
     if (userconfig) {
-        if (qemu_read_default_config_file() < 0) {
-            exit(1);
-        }
+        qemu_read_default_config_file(&error_fatal);
     }
 
     /* second pass of option parsing */
@@ -3292,15 +3289,8 @@ void qemu_init(int argc, char **argv, char **envp)
                 qemu_plugin_opt_parse(optarg, &plugin_list);
                 break;
             case QEMU_OPTION_readconfig:
-                {
-                    int ret = qemu_read_config_file(optarg);
-                    if (ret < 0) {
-                        error_report("read config %s: %s", optarg,
-                                     strerror(-ret));
-                        exit(1);
-                    }
-                    break;
-                }
+                qemu_read_config_file(optarg, &error_fatal);
+                break;
             case QEMU_OPTION_spice:
                 olist = qemu_find_opts_err("spice", NULL);
                 if (!olist) {
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 725e3d7e4b..7804333b5a 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -356,7 +356,7 @@ void qemu_config_write(FILE *fp)
 }
 
 /* Returns number of config groups on success, -errno on error */
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
+int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
 {
     char line[1024], group[64], id[64], arg[64], value[1024];
     Location loc;
@@ -381,7 +381,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
             /* group with id */
             list = find_list(lists, group, &local_err);
             if (local_err) {
-                error_report_err(local_err);
+                error_propagate(errp, local_err);
                 goto out;
             }
             opts = qemu_opts_create(list, id, 1, NULL);
@@ -392,7 +392,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
             /* group without id */
             list = find_list(lists, group, &local_err);
             if (local_err) {
-                error_report_err(local_err);
+                error_propagate(errp, local_err);
                 goto out;
             }
             opts = qemu_opts_create(list, NULL, 0, &error_abort);
@@ -404,20 +404,19 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
             sscanf(line, " %63s = \"\"", arg) == 1) {
             /* arg = value */
             if (opts == NULL) {
-                error_report("no group defined");
+                error_setg(errp, "no group defined");
                 goto out;
             }
-            if (!qemu_opt_set(opts, arg, value, &local_err)) {
-                error_report_err(local_err);
+            if (!qemu_opt_set(opts, arg, value, errp)) {
                 goto out;
             }
             continue;
         }
-        error_report("parse error");
+        error_setg(errp, "parse error");
         goto out;
     }
     if (ferror(fp)) {
-        error_report("error reading file");
+        error_setg(errp, "error reading file");
         goto out;
     }
     res = count;
@@ -426,16 +425,17 @@ out:
     return res;
 }
 
-int qemu_read_config_file(const char *filename)
+int qemu_read_config_file(const char *filename, Error **errp)
 {
     FILE *f = fopen(filename, "r");
     int ret;
 
     if (f == NULL) {
+        error_setg_errno(errp, errno, "Cannot read config file %s", filename);
         return -errno;
     }
 
-    ret = qemu_config_parse(f, vm_config_groups, filename);
+    ret = qemu_config_parse(f, vm_config_groups, filename, errp);
     fclose(f);
     return ret;
 }
-- 
2.26.2




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

* [PATCH 10/12] qemu-option: support accept-any QemuOptsList in qemu_opts_absorb_qdict
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (8 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 09/12] qemu-config: add error propagation to qemu_config_parse Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 11/12] qemu-config: parse configuration files to a QDict Paolo Bonzini
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 util/qemu-option.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/util/qemu-option.c b/util/qemu-option.c
index 40564a12eb..afba08d92e 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -1052,7 +1052,8 @@ bool qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
     while (entry != NULL) {
         next = qdict_next(qdict, entry);
 
-        if (find_desc_by_name(opts->list->desc, entry->key)) {
+        if (opts_accepts_any(opts->list) ||
+            find_desc_by_name(opts->list->desc, entry->key)) {
             if (!qemu_opts_from_qdict_entry(opts, entry, errp)) {
                 return false;
             }
-- 
2.26.2




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

* [PATCH 11/12] qemu-config: parse configuration files to a QDict
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (9 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 10/12] qemu-option: support accept-any QemuOptsList in qemu_opts_absorb_qdict Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-11 14:25 ` [PATCH 12/12] qemu: use keyval for -object parsing Paolo Bonzini
  2020-11-13 14:35 ` [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Kevin Wolf
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Change the parser to put the values into a QDict and pass them
to a callback.  qemu_config_parse's QemuOpts creation is
itself turned into a callback function.

Note that the QemuOpts are now created at the _end_ of the group,
rather than at the beginning.  Therefore, loc_set_file is delayed
until after the callback has been invoked.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/qemu/config-file.h |  6 ++-
 softmmu/vl.c               |  4 +-
 util/qemu-config.c         | 91 +++++++++++++++++++++++++-------------
 3 files changed, 68 insertions(+), 33 deletions(-)

diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
index 4e235f63ce..6f9b511f48 100644
--- a/include/qemu/config-file.h
+++ b/include/qemu/config-file.h
@@ -1,6 +1,7 @@
 #ifndef QEMU_CONFIG_FILE_H
 #define QEMU_CONFIG_FILE_H
 
+typedef void QEMUConfigCB(const char *group, QDict *qdict, void *opaque, Error **errp);
 
 QemuOptsList *qemu_find_opts(const char *group);
 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
@@ -13,7 +14,10 @@ int qemu_global_option(const char *str);
 void qemu_config_write(FILE *fp);
 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp);
 
-int qemu_read_config_file(const char *filename, Error **errp);
+/* A default callback for qemu_read_config_file().  */
+void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp);
+
+int qemu_read_config_file(const char *filename, QEMUConfigCB *f, Error **errp);
 
 /* Parse QDict options as a replacement for a config file (allowing multiple
    enumerated (0..(n-1)) configuration "sections") */
diff --git a/softmmu/vl.c b/softmmu/vl.c
index e46f286ad2..9b3b687a85 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2047,7 +2047,7 @@ static void qemu_read_default_config_file(Error **errp)
     Error *local_err = NULL;
     g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
 
-    ret = qemu_read_config_file(file, &local_err);
+    ret = qemu_read_config_file(file, qemu_config_do_parse, &local_err);
     if (ret < 0 && ret != -ENOENT) {
         error_propagate(errp, local_err);
     }
@@ -3289,7 +3289,7 @@ void qemu_init(int argc, char **argv, char **envp)
                 qemu_plugin_opt_parse(optarg, &plugin_list);
                 break;
             case QEMU_OPTION_readconfig:
-                qemu_read_config_file(optarg, &error_fatal);
+                qemu_read_config_file(optarg, qemu_config_do_parse, &error_fatal);
                 break;
             case QEMU_OPTION_spice:
                 olist = qemu_find_opts_err("spice", NULL);
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 7804333b5a..a1db99dcba 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -356,19 +356,19 @@ void qemu_config_write(FILE *fp)
 }
 
 /* Returns number of config groups on success, -errno on error */
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
+static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque,
+                               const char *fname, Error **errp)
 {
-    char line[1024], group[64], id[64], arg[64], value[1024];
+    char line[1024], prev_group[64], group[64], arg[64], value[1024];
     Location loc;
-    QemuOptsList *list = NULL;
     Error *local_err = NULL;
-    QemuOpts *opts = NULL;
+    QDict *qdict = NULL;
     int res = -EINVAL, lno = 0;
     int count = 0;
 
     loc_push_none(&loc);
     while (fgets(line, sizeof(line), fp) != NULL) {
-        loc_set_file(fname, ++lno);
+        ++lno;
         if (line[0] == '\n') {
             /* skip empty lines */
             continue;
@@ -377,39 +377,39 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
             /* comment */
             continue;
         }
-        if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
-            /* group with id */
-            list = find_list(lists, group, &local_err);
-            if (local_err) {
-                error_propagate(errp, local_err);
-                goto out;
+        if (line[0] == '[') {
+            QDict *prev = qdict;
+            if (sscanf(line, "[%63s \"%63[^\"]\"]", group, value) == 2) {
+                qdict = qdict_new();
+                qdict_put_str(qdict, "id", value);
+                count++;
+            } else if (sscanf(line, "[%63[^]]]", group) == 1) {
+                qdict = qdict_new();
+                count++;
             }
-            opts = qemu_opts_create(list, id, 1, NULL);
-            count++;
-            continue;
-        }
-        if (sscanf(line, "[%63[^]]]", group) == 1) {
-            /* group without id */
-            list = find_list(lists, group, &local_err);
-            if (local_err) {
-                error_propagate(errp, local_err);
-                goto out;
+            if (qdict != prev) {
+                if (prev) {
+                    cb(prev_group, prev, opaque, &local_err);
+                    qobject_unref(prev);
+                    if (local_err) {
+                        error_propagate(errp, local_err);
+                        goto out;
+                    }
+                }
+                strcpy(prev_group, group);
+                continue;
             }
-            opts = qemu_opts_create(list, NULL, 0, &error_abort);
-            count++;
-            continue;
         }
+        loc_set_file(fname, lno);
         value[0] = '\0';
         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
             sscanf(line, " %63s = \"\"", arg) == 1) {
             /* arg = value */
-            if (opts == NULL) {
+            if (qdict == NULL) {
                 error_setg(errp, "no group defined");
                 goto out;
             }
-            if (!qemu_opt_set(opts, arg, value, errp)) {
-                goto out;
-            }
+            qdict_put_str(qdict, arg, value);
             continue;
         }
         error_setg(errp, "parse error");
@@ -422,10 +422,41 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
     res = count;
 out:
     loc_pop(&loc);
+    if (qdict) {
+        cb(group, qdict, opaque, errp);
+        qobject_unref(qdict);
+    }
     return res;
 }
 
-int qemu_read_config_file(const char *filename, Error **errp)
+void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp)
+{
+    QemuOptsList **lists = opaque;
+    const char *id = qdict_get_try_str(qdict, "id");
+    QemuOptsList *list;
+    QemuOpts *opts;
+
+    list = find_list(lists, group, errp);
+    if (!list) {
+        return;
+    }
+
+    opts = qemu_opts_create(list, id, 1, errp);
+    if (!opts) {
+        return;
+    }
+    if (id) {
+        qdict_del(qdict, "id");
+    }
+    qemu_opts_absorb_qdict(opts, qdict, errp);
+}
+
+int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
+{
+    return qemu_config_foreach(fp, qemu_config_do_parse, lists, fname, errp);
+}
+
+int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp)
 {
     FILE *f = fopen(filename, "r");
     int ret;
@@ -435,7 +466,7 @@ int qemu_read_config_file(const char *filename, Error **errp)
         return -errno;
     }
 
-    ret = qemu_config_parse(f, vm_config_groups, filename, errp);
+    ret = qemu_config_foreach(f, cb, vm_config_groups, filename, errp);
     fclose(f);
     return ret;
 }
-- 
2.26.2




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

* [PATCH 12/12] qemu: use keyval for -object parsing
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (10 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 11/12] qemu-config: parse configuration files to a QDict Paolo Bonzini
@ 2020-11-11 14:25 ` Paolo Bonzini
  2020-11-13 14:35 ` [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Kevin Wolf
  12 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2020-11-11 14:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/qom/object_interfaces.h | 44 ----------------
 qom/object_interfaces.c         | 42 ---------------
 softmmu/vl.c                    | 93 ++++++++++++++++++++++-----------
 3 files changed, 63 insertions(+), 116 deletions(-)

diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
index abb23eaea3..77a4d5cf98 100644
--- a/include/qom/object_interfaces.h
+++ b/include/qom/object_interfaces.h
@@ -119,36 +119,6 @@ bool user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
  */
 Object *user_creatable_add_opts(QemuOpts *opts, Error **errp);
 
-
-/**
- * user_creatable_add_opts_predicate:
- * @type: the QOM type to be added
- *
- * A callback function to determine whether an object
- * of type @type should be created. Instances of this
- * callback should be passed to user_creatable_add_opts_foreach
- */
-typedef bool (*user_creatable_add_opts_predicate)(const char *type);
-
-/**
- * user_creatable_add_opts_foreach:
- * @opaque: a user_creatable_add_opts_predicate callback or NULL
- * @opts: options to create
- * @errp: unused
- *
- * An iterator callback to be used in conjunction with
- * the qemu_opts_foreach() method for creating a list of
- * objects from a set of QemuOpts
- *
- * The @opaque parameter can be passed a user_creatable_add_opts_predicate
- * callback to filter which types of object are created during iteration.
- * When it fails, report the error.
- *
- * Returns: 0 on success, -1 when an error was reported.
- */
-int user_creatable_add_opts_foreach(void *opaque,
-                                    QemuOpts *opts, Error **errp);
-
 /**
  * user_creatable_print_types:
  *
@@ -156,20 +126,6 @@ int user_creatable_add_opts_foreach(void *opaque,
  */
 void user_creatable_print_types(void);
 
-/**
- * user_creatable_print_help:
- * @type: the QOM type to be added
- * @opts: options to create
- *
- * Prints help if requested in @type or @opts. Note that if @type is neither
- * "help"/"?" nor a valid user creatable type, no help will be printed
- * regardless of @opts.
- *
- * Returns: true if a help option was found and help was printed, false
- * otherwise.
- */
-bool user_creatable_print_help(const char *type, QemuOpts *opts);
-
 /**
  * user_creatable_print_help_from_qdict:
  * @args: options to create
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index f7dcdf18e2..08d1f5c0d5 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -171,27 +171,6 @@ Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
     return obj;
 }
 
-
-int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
-{
-    bool (*type_opt_predicate)(const char *, QemuOpts *) = opaque;
-    Object *obj = NULL;
-    const char *type;
-
-    type = qemu_opt_get(opts, "qom-type");
-    if (type && type_opt_predicate &&
-        !type_opt_predicate(type, opts)) {
-        return 0;
-    }
-
-    obj = user_creatable_add_opts(opts, errp);
-    if (!obj) {
-        return -1;
-    }
-    object_unref(obj);
-    return 0;
-}
-
 char *object_property_help(const char *name, const char *type,
                            QObject *defval, const char *description)
 {
@@ -266,20 +245,6 @@ static bool user_creatable_print_type_properites(const char *type)
     return true;
 }
 
-bool user_creatable_print_help(const char *type, QemuOpts *opts)
-{
-    if (is_help_option(type)) {
-        user_creatable_print_types();
-        return true;
-    }
-
-    if (qemu_opt_has_help_opt(opts)) {
-        return user_creatable_print_type_properites(type);
-    }
-
-    return false;
-}
-
 void user_creatable_print_help_from_qdict(const QDict *args)
 {
     const char *type = qdict_get_try_str(args, "qom-type");
@@ -306,13 +271,6 @@ bool user_creatable_del(const char *id, Error **errp)
         return false;
     }
 
-    /*
-     * if object was defined on the command-line, remove its corresponding
-     * option group entry
-     */
-    qemu_opts_del(qemu_opts_find(qemu_find_opts_err("object", &error_abort),
-                                 id));
-
     object_unparent(obj);
     return true;
 }
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 9b3b687a85..bb4dc87a29 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -116,6 +116,7 @@
 #include "qapi/qapi-commands-migration.h"
 #include "qapi/qapi-commands-misc.h"
 #include "qapi/qapi-commands-ui.h"
+#include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/iothread.h"
 #include "qemu/guest-random.h"
@@ -136,6 +137,7 @@ static const char *boot_order;
 static const char *boot_once;
 static const char *incoming;
 static const char *loadvm;
+static GSList *object_opts_list = NULL;
 static ram_addr_t maxram_size;
 static uint64_t ram_slots;
 static int display_remote;
@@ -308,15 +310,6 @@ static QemuOptsList qemu_add_fd_opts = {
     },
 };
 
-static QemuOptsList qemu_object_opts = {
-    .name = "object",
-    .implied_opt_name = "qom-type",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
-    .desc = {
-        { }
-    },
-};
-
 static QemuOptsList qemu_tpmdev_opts = {
     .name = "tpmdev",
     .implied_opt_name = "type",
@@ -1678,12 +1671,8 @@ static int machine_set_property(void *opaque,
  * cannot be created here, as it depends on the chardev
  * already existing.
  */
-static bool object_create_early(const char *type, QemuOpts *opts)
+static bool object_create_early(const char *type)
 {
-    if (user_creatable_print_help(type, opts)) {
-        exit(0);
-    }
-
     /*
      * Objects should not be made "delayed" without a reason.  If you
      * add one, state the reason in a comment!
@@ -1769,6 +1758,22 @@ static void qemu_apply_machine_options(void)
     current_machine->boot_order = boot_order;
 }
 
+static void user_creatable_add_dict_foreach(void *data, void *opaque)
+{
+    bool (*type_opt_predicate)(const char *) = opaque;
+    QDict *dict = data;
+    const char *type = qdict_get_try_str(dict, "qom-type");
+
+    if (!type) {
+        error_report("Parameter 'qom-type' is missing");
+    }
+    if (type_opt_predicate && !type_opt_predicate(type)) {
+        return;
+    }
+
+    user_creatable_add_dict(dict, true, &error_fatal);
+}
+
 static void qemu_create_early_backends(void)
 {
     MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
@@ -1795,9 +1800,9 @@ static void qemu_create_early_backends(void)
         exit(1);
     }
 
-    qemu_opts_foreach(qemu_find_opts("object"),
-                      user_creatable_add_opts_foreach,
-                      object_create_early, &error_fatal);
+    g_slist_foreach(object_opts_list,
+                    user_creatable_add_dict_foreach,
+                    object_create_early);
 
     /* spice needs the timers to be initialized by this point */
     /* spice must initialize before audio as it changes the default auiodev */
@@ -1826,9 +1831,9 @@ static void qemu_create_early_backends(void)
  * The remainder of object creation happens after the
  * creation of chardev, fsdev, net clients and device data types.
  */
-static bool object_create_late(const char *type, QemuOpts *opts)
+static bool object_create_late(const char *type)
 {
-    return !object_create_early(type, opts);
+    return !object_create_early(type);
 }
 
 static void qemu_create_late_backends(void)
@@ -1839,9 +1844,9 @@ static void qemu_create_late_backends(void)
 
     net_init_clients(&error_fatal);
 
-    qemu_opts_foreach(qemu_find_opts("object"),
-                      user_creatable_add_opts_foreach,
-                      object_create_late, &error_fatal);
+    g_slist_foreach(object_opts_list,
+                    user_creatable_add_dict_foreach,
+                    object_create_late);
 
     if (tpm_init() < 0) {
         exit(1);
@@ -2041,13 +2046,32 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
     return 0;
 }
 
+/*
+ * Parse non-QemuOpts config file groups, pass the rest to
+ * qemu_config_do_parse.
+ */
+static void qemu_parse_config_group(const char *group, QDict *qdict,
+                                    void *opaque, Error **errp)
+{
+    if (g_str_equal(group, "object")) {
+        QObject *crumpled = qdict_crumple(qdict, errp);
+        if (!crumpled) {
+            return;
+        }
+        object_opts_list = g_slist_prepend(object_opts_list, crumpled);
+        return;
+    }
+
+    qemu_config_do_parse(group, qdict, opaque, errp);
+}
+
 static void qemu_read_default_config_file(Error **errp)
 {
     int ret;
     Error *local_err = NULL;
     g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
 
-    ret = qemu_read_config_file(file, qemu_config_do_parse, &local_err);
+    ret = qemu_read_config_file(file, qemu_parse_config_group, &local_err);
     if (ret < 0 && ret != -ENOENT) {
         error_propagate(errp, local_err);
     }
@@ -2561,7 +2585,6 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_add_opts(&qemu_smp_opts);
     qemu_add_opts(&qemu_boot_opts);
     qemu_add_opts(&qemu_add_fd_opts);
-    qemu_add_opts(&qemu_object_opts);
     qemu_add_opts(&qemu_tpmdev_opts);
     qemu_add_opts(&qemu_realtime_opts);
     qemu_add_opts(&qemu_overcommit_opts);
@@ -3289,7 +3312,7 @@ void qemu_init(int argc, char **argv, char **envp)
                 qemu_plugin_opt_parse(optarg, &plugin_list);
                 break;
             case QEMU_OPTION_readconfig:
-                qemu_read_config_file(optarg, qemu_config_do_parse, &error_fatal);
+                qemu_read_config_file(optarg, qemu_parse_config_group, &error_fatal);
                 break;
             case QEMU_OPTION_spice:
                 olist = qemu_find_opts_err("spice", NULL);
@@ -3361,12 +3384,18 @@ void qemu_init(int argc, char **argv, char **envp)
 #endif
                 break;
             case QEMU_OPTION_object:
-                opts = qemu_opts_parse_noisily(qemu_find_opts("object"),
-                                               optarg, true);
-                if (!opts) {
-                    exit(1);
+                {
+                    QDict *args;
+                    bool help;
+
+                    args = keyval_parse(optarg, "qom-type", &help, &error_fatal);
+                    if (help) {
+                        user_creatable_print_help_from_qdict(args);
+                        exit(EXIT_SUCCESS);
+                    }
+                    object_opts_list = g_slist_prepend(object_opts_list, args);
+                    break;
                 }
-                break;
             case QEMU_OPTION_realtime:
                 warn_report("'-realtime mlock=...' is deprecated, please use "
                              "'-overcommit mem-lock=...' instead");
@@ -3424,6 +3453,10 @@ void qemu_init(int argc, char **argv, char **envp)
             }
         }
     }
+
+    /* Cleanup after option parsing loop.  */
+    object_opts_list = g_slist_reverse(object_opts_list);
+
     /*
      * Clear error location left behind by the loop.
      * Best done right after the loop.  Do not insert code here!
-- 
2.26.2



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

* Re: [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig
  2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
                   ` (11 preceding siblings ...)
  2020-11-11 14:25 ` [PATCH 12/12] qemu: use keyval for -object parsing Paolo Bonzini
@ 2020-11-13 14:35 ` Kevin Wolf
  12 siblings, 0 replies; 14+ messages in thread
From: Kevin Wolf @ 2020-11-13 14:35 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Am 11.11.2020 um 15:25 hat Paolo Bonzini geschrieben:
> This is yet another RFC on the command-line parsing overhaul.  Here,
> I'm switching HMP, -object and -readconfig away from QemuOpts.  There are
> pending QemuOpts and keyval patches that make the syntaxes the same
> apart from:
> 
> - "implicit value" options (where the lack of value is turned
> into "on" or "off"), which will be deprecated
> 
> - the processing of invalid, empty or overlong keys which can be considered
> bugfixes.
> 
> Along the way, the object_add HMP command grows help support.
> 
> The plan on top of this is to also keyval-ify -M and -accel.  The reason
> for this, in my evil plan, is to allow for compound properties.  These
> compound properties would be used for replacements of options like -smp
> (-M smp.xxx), -icount (-accel tcg,icount.xxx) and -chardev (as in -object
> chardev-socket,addr.host).

I haven't reviewed everything in detail, but this approach looks
workable to me.

Of course, at the moment -object is a bit different from other options
in that it doesn't have a QAPI object for the options, but you just
directly pass QDicts to user_creatable_add_dict(). But plugging in a
visitor for other options groups doesn't suddenly require a different
design, so this is fine.

Kevin



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

end of thread, other threads:[~2020-11-13 14:36 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-11 14:25 [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Paolo Bonzini
2020-11-11 14:25 ` [PATCH 01/12] tests: convert check-qom-proplist to keyval Paolo Bonzini
2020-11-11 14:25 ` [PATCH 02/12] keyval: introduce keyval_parse_into Paolo Bonzini
2020-11-11 14:25 ` [PATCH 03/12] hmp: replace "O" parser with keyval Paolo Bonzini
2020-11-11 14:25 ` [PATCH 04/12] qom: use qemu_printf to print help for user-creatable objects Paolo Bonzini
2020-11-11 14:25 ` [PATCH 05/12] hmp: special case help options for object_add Paolo Bonzini
2020-11-11 14:25 ` [PATCH 06/12] qemu-io: use keyval for -object parsing Paolo Bonzini
2020-11-11 14:25 ` [PATCH 07/12] qemu-nbd: " Paolo Bonzini
2020-11-11 14:25 ` [PATCH 08/12] qemu-img: " Paolo Bonzini
2020-11-11 14:25 ` [PATCH 09/12] qemu-config: add error propagation to qemu_config_parse Paolo Bonzini
2020-11-11 14:25 ` [PATCH 10/12] qemu-option: support accept-any QemuOptsList in qemu_opts_absorb_qdict Paolo Bonzini
2020-11-11 14:25 ` [PATCH 11/12] qemu-config: parse configuration files to a QDict Paolo Bonzini
2020-11-11 14:25 ` [PATCH 12/12] qemu: use keyval for -object parsing Paolo Bonzini
2020-11-13 14:35 ` [RFC PATCH 00/12] Remove QemuOpts usage for HMP, -object and -readconfig Kevin Wolf

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.