From d9c8b54b44b85f7648e7069abfb20cd0ec439a03 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Jun 01 2021 07:35:27 +0000 Subject: add missing patches --- diff --git a/0001-vl-allow-not-specifying-size-in-m-when-using-M-memor.patch b/0001-vl-allow-not-specifying-size-in-m-when-using-M-memor.patch new file mode 100644 index 0000000..de846ed --- /dev/null +++ b/0001-vl-allow-not-specifying-size-in-m-when-using-M-memor.patch @@ -0,0 +1,46 @@ +From 7de096767b5e65d105168fbd5130397f9fbda626 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 18 May 2021 12:35:31 +0200 +Subject: [PATCH 1/5] vl: allow not specifying size in -m when using -M + memory-backend + +Starting in QEMU 6.0's commit f5c9fcb82d ("vl: separate +qemu_create_machine", 2020-12-10), a function have_custom_ram_size() +replaced the return value of set_memory_options(). + +The purpose of the return value was to record the presence of +"-m size", and if it was not there, change the default RAM +size to the size of the memory backend passed with "-M +memory-backend". + +With that commit, however, have_custom_ram_size() is now queried only +after set_memory_options has stored the fixed-up RAM size in QemuOpts for +"future use". This was actually the only future use of the fixed-up RAM +size, so remove that code and fix the bug. + +Cc: qemu-stable@nongnu.org +Fixes: f5c9fcb82d ("vl: separate qemu_create_machine", 2020-12-10) +Signed-off-by: Paolo Bonzini +Reviewed-by: Igor Mammedov +Message-Id: <20210518103531.104162-1-pbonzini@redhat.com> +Signed-off-by: Paolo Bonzini +--- + softmmu/vl.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/softmmu/vl.c b/softmmu/vl.c +index aadb526..29d6415 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -2025,8 +2025,6 @@ static void set_memory_options(MachineClass *mc) + exit(EXIT_FAILURE); + } + +- /* store value for the future use */ +- qemu_opt_set_number(opts, "size", ram_size, &error_abort); + maxram_size = ram_size; + + if (qemu_opt_get(opts, "maxmem")) { +-- +2.31.1 + diff --git a/0002-qemu-config-load-modules-when-instantiating-option-g.patch b/0002-qemu-config-load-modules-when-instantiating-option-g.patch new file mode 100644 index 0000000..a81a621 --- /dev/null +++ b/0002-qemu-config-load-modules-when-instantiating-option-g.patch @@ -0,0 +1,120 @@ +From 7b861d20e22278fc5915f03d77b83e07ba44d440 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 18 May 2021 09:15:42 -0400 +Subject: [PATCH 2/5] qemu-config: load modules when instantiating option + groups + +Right now the SPICE module is special cased to be loaded when processing +of the -spice command line option. However, the spice option group +can also be brought in via -readconfig, in which case the module is +not loaded. + +Add a generic hook to load modules that provide a QemuOpts group, +and use it for the "spice" and "iscsi" groups. + +Fixes: #194 +Fixes: https://bugs.launchpad.net/qemu/+bug/1910696 +Signed-off-by: Paolo Bonzini +Reviewed-by: Gerd Hoffmann +Message-Id: <20210518131542.2941207-1-pbonzini@redhat.com> +Signed-off-by: Paolo Bonzini +--- + include/qemu/config-file.h | 2 +- + softmmu/vl.c | 21 +++++++++++++++++---- + stubs/meson.build | 1 + + stubs/module-opts.c | 6 ++++++ + util/qemu-config.c | 1 + + 5 files changed, 26 insertions(+), 5 deletions(-) + create mode 100644 stubs/module-opts.c + +diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h +index 8d3e53a..0500b36 100644 +--- a/include/qemu/config-file.h ++++ b/include/qemu/config-file.h +@@ -1,7 +1,7 @@ + #ifndef QEMU_CONFIG_FILE_H + #define QEMU_CONFIG_FILE_H + +- ++void qemu_load_module_for_opts(const char *group); + QemuOptsList *qemu_find_opts(const char *group); + QemuOptsList *qemu_find_opts_err(const char *group, Error **errp); + QemuOpts *qemu_find_opts_singleton(const char *group); +diff --git a/softmmu/vl.c b/softmmu/vl.c +index 29d6415..4641f08 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -2613,6 +2613,23 @@ void qmp_x_exit_preconfig(Error **errp) + } + } + ++#ifdef CONFIG_MODULES ++void qemu_load_module_for_opts(const char *group) ++{ ++ static bool spice_tried = false; ++ if (g_str_equal(group, "spice") && !spice_tried) { ++ ui_module_load_one("spice-core"); ++ spice_tried = true; ++ } ++ ++ static bool iscsi_tried = false; ++ if (g_str_equal(group, "iscsi") && !iscsi_tried) { ++ block_module_load_one("iscsi"); ++ iscsi_tried = true; ++ } ++} ++#endif ++ + void qemu_init(int argc, char **argv, char **envp) + { + QemuOpts *opts; +@@ -3372,10 +3389,6 @@ void qemu_init(int argc, char **argv, char **envp) + break; + case QEMU_OPTION_spice: + olist = qemu_find_opts_err("spice", NULL); +- if (!olist) { +- ui_module_load_one("spice-core"); +- olist = qemu_find_opts("spice"); +- } + if (!olist) { + error_report("spice support is disabled"); + exit(1); +diff --git a/stubs/meson.build b/stubs/meson.build +index be6f6d6..5555b69 100644 +--- a/stubs/meson.build ++++ b/stubs/meson.build +@@ -22,6 +22,7 @@ stub_ss.add(files('isa-bus.c')) + stub_ss.add(files('is-daemonized.c')) + stub_ss.add(when: 'CONFIG_LINUX_AIO', if_true: files('linux-aio.c')) + stub_ss.add(files('migr-blocker.c')) ++stub_ss.add(files('module-opts.c')) + stub_ss.add(files('monitor.c')) + stub_ss.add(files('monitor-core.c')) + stub_ss.add(files('pci-bus.c')) +diff --git a/stubs/module-opts.c b/stubs/module-opts.c +new file mode 100644 +index 0000000..a7d0e4a +--- /dev/null ++++ b/stubs/module-opts.c +@@ -0,0 +1,6 @@ ++#include "qemu/osdep.h" ++#include "qemu/config-file.h" ++ ++void qemu_load_module_for_opts(const char *group) ++{ ++} +diff --git a/util/qemu-config.c b/util/qemu-config.c +index 670bd6e..34974c4 100644 +--- a/util/qemu-config.c ++++ b/util/qemu-config.c +@@ -16,6 +16,7 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group, + { + int i; + ++ qemu_load_module_for_opts(group); + for (i = 0; lists[i] != NULL; i++) { + if (strcmp(lists[i]->name, group) == 0) + break; +-- +2.31.1 + diff --git a/0003-qemu-config-parse-configuration-files-to-a-QDict.patch b/0003-qemu-config-parse-configuration-files-to-a-QDict.patch new file mode 100644 index 0000000..f0568a4 --- /dev/null +++ b/0003-qemu-config-parse-configuration-files-to-a-QDict.patch @@ -0,0 +1,236 @@ +From a0520e180e6f235b8a3a531b0756e45cbfe36e15 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 18 May 2021 11:40:57 -0400 +Subject: [PATCH 3/5] qemu-config: parse configuration files to a QDict + +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. + +This is useful for -readconfig to support keyval-based options; +getting a QDict from the parser removes a roundtrip from +QDict to QemuOpts and then back to QDict. + +Unfortunately there is a disadvantage in that semantic errors will +point to the last line of the group, because the entries of the QDict +do not have a location attached. + +Cc: Kevin Wolf +Cc: Markus Armbruster +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Message-Id: <20210524105752.3318299-2-pbonzini@redhat.com> +--- + include/qemu/config-file.h | 7 ++- + softmmu/vl.c | 4 +- + util/qemu-config.c | 97 ++++++++++++++++++++++++++------------ + 3 files changed, 75 insertions(+), 33 deletions(-) + +diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h +index 0500b36..f605423 100644 +--- a/include/qemu/config-file.h ++++ b/include/qemu/config-file.h +@@ -1,6 +1,8 @@ + #ifndef QEMU_CONFIG_FILE_H + #define QEMU_CONFIG_FILE_H + ++typedef void QEMUConfigCB(const char *group, QDict *qdict, void *opaque, Error **errp); ++ + void qemu_load_module_for_opts(const char *group); + QemuOptsList *qemu_find_opts(const char *group); + QemuOptsList *qemu_find_opts_err(const char *group, Error **errp); +@@ -14,7 +16,10 @@ 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 4641f08..da5042f 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -2119,7 +2119,7 @@ static void qemu_read_default_config_file(Error **errp) + int ret; + g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf"); + +- ret = qemu_read_config_file(file, errp); ++ ret = qemu_read_config_file(file, qemu_config_do_parse, errp); + if (ret < 0) { + if (ret == -ENOENT) { + error_free(*errp); +@@ -3385,7 +3385,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 34974c4..f6eaff9 100644 +--- a/util/qemu-config.c ++++ b/util/qemu-config.c +@@ -2,6 +2,7 @@ + #include "block/qdict.h" /* for qdict_extract_subqdict() */ + #include "qapi/error.h" + #include "qapi/qapi-commands-misc.h" ++#include "qapi/qmp/qerror.h" + #include "qapi/qmp/qdict.h" + #include "qapi/qmp/qlist.h" + #include "qemu/error-report.h" +@@ -351,19 +352,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; +@@ -372,39 +373,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"); +@@ -417,11 +418,47 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error * + } + res = count; + out: ++ if (qdict) { ++ cb(group, qdict, opaque, errp); ++ qobject_unref(qdict); ++ } + loc_pop(&loc); + 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; ++ const QDictEntry *unrecognized; ++ ++ list = find_list(lists, group, errp); ++ if (!list) { ++ return; ++ } ++ ++ opts = qemu_opts_create(list, id, 1, errp); ++ if (!opts) { ++ return; ++ } ++ if (!qemu_opts_absorb_qdict(opts, qdict, errp)) { ++ return; ++ } ++ unrecognized = qdict_first(qdict); ++ if (unrecognized) { ++ error_setg(errp, QERR_INVALID_PARAMETER, unrecognized->key); ++ qemu_opts_del(opts); ++ } ++} ++ ++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; +@@ -431,7 +468,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.31.1 + diff --git a/0004-vl-plumb-keyval-based-options-into-readconfig.patch b/0004-vl-plumb-keyval-based-options-into-readconfig.patch new file mode 100644 index 0000000..d49c203 --- /dev/null +++ b/0004-vl-plumb-keyval-based-options-into-readconfig.patch @@ -0,0 +1,187 @@ +From 8eef1078eff6fc5cc045684486d228153463dac2 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 18 May 2021 11:40:58 -0400 +Subject: [PATCH 4/5] vl: plumb keyval-based options into -readconfig + +Let -readconfig support parsing command line options into QDict or +QemuOpts. This will be used to add back support for objects in +-readconfig. + +Cc: Markus Armbruster +Cc: qemu-stable@nongnu.org +Reviewed-by: Kevin Wolf +Signed-off-by: Paolo Bonzini +Message-Id: <20210524105752.3318299-3-pbonzini@redhat.com> +--- + include/block/qdict.h | 2 - + include/qapi/qmp/qdict.h | 3 ++ + softmmu/vl.c | 83 ++++++++++++++++++++++++++++------------ + 3 files changed, 62 insertions(+), 26 deletions(-) + +diff --git a/include/block/qdict.h b/include/block/qdict.h +index d8cb502..ced2acf 100644 +--- a/include/block/qdict.h ++++ b/include/block/qdict.h +@@ -20,8 +20,6 @@ void qdict_join(QDict *dest, QDict *src, bool overwrite); + void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start); + void qdict_array_split(QDict *src, QList **dst); + int qdict_array_entries(QDict *src, const char *subqdict); +-QObject *qdict_crumple(const QDict *src, Error **errp); +-void qdict_flatten(QDict *qdict); + + typedef struct QDictRenames { + const char *from; +diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h +index 9934539..d5b5430 100644 +--- a/include/qapi/qmp/qdict.h ++++ b/include/qapi/qmp/qdict.h +@@ -64,4 +64,7 @@ const char *qdict_get_try_str(const QDict *qdict, const char *key); + + QDict *qdict_clone_shallow(const QDict *src); + ++QObject *qdict_crumple(const QDict *src, Error **errp); ++void qdict_flatten(QDict *qdict); ++ + #endif /* QDICT_H */ +diff --git a/softmmu/vl.c b/softmmu/vl.c +index da5042f..48d1f06 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -122,6 +122,7 @@ + #include "qapi/qapi-commands-misc.h" + #include "qapi/qapi-visit-qom.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" +@@ -2113,13 +2114,53 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp) + return 0; + } + ++/* ++ * Return whether configuration group @group is stored in QemuOpts, or ++ * recorded as one or more QDicts by qemu_record_config_group. ++ */ ++static bool is_qemuopts_group(const char *group) ++{ ++ return true; ++} ++ ++static void qemu_record_config_group(const char *group, QDict *dict, ++ bool from_json, Error **errp) ++{ ++ abort(); ++} ++ ++/* ++ * 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) ++{ ++ QObject *crumpled; ++ if (is_qemuopts_group(group)) { ++ qemu_config_do_parse(group, qdict, opaque, errp); ++ return; ++ } ++ ++ crumpled = qdict_crumple(qdict, errp); ++ if (!crumpled) { ++ return; ++ } ++ if (qobject_type(crumpled) != QTYPE_QDICT) { ++ assert(qobject_type(crumpled) == QTYPE_QLIST); ++ error_setg(errp, "Lists cannot be at top level of a configuration section"); ++ return; ++ } ++ qemu_record_config_group(group, qobject_to(QDict, crumpled), false, errp); ++} ++ + static void qemu_read_default_config_file(Error **errp) + { + ERRP_GUARD(); + int ret; + g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf"); + +- ret = qemu_read_config_file(file, qemu_config_do_parse, errp); ++ ret = qemu_read_config_file(file, qemu_parse_config_group, errp); + if (ret < 0) { + if (ret == -ENOENT) { + error_free(*errp); +@@ -2128,9 +2169,8 @@ static void qemu_read_default_config_file(Error **errp) + } + } + +-static int qemu_set_option(const char *str) ++static void qemu_set_option(const char *str, Error **errp) + { +- Error *local_err = NULL; + char group[64], id[64], arg[64]; + QemuOptsList *list; + QemuOpts *opts; +@@ -2138,27 +2178,23 @@ static int qemu_set_option(const char *str) + + rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); + if (rc < 3 || str[offset] != '=') { +- error_report("can't parse: \"%s\"", str); +- return -1; +- } +- +- list = qemu_find_opts(group); +- if (list == NULL) { +- return -1; +- } +- +- opts = qemu_opts_find(list, id); +- if (!opts) { +- error_report("there is no %s \"%s\" defined", +- list->name, id); +- return -1; ++ error_setg(errp, "can't parse: \"%s\"", str); ++ return; + } + +- if (!qemu_opt_set(opts, arg, str + offset + 1, &local_err)) { +- error_report_err(local_err); +- return -1; ++ if (!is_qemuopts_group(group)) { ++ error_setg(errp, "-set is not supported with %s", group); ++ } else { ++ list = qemu_find_opts_err(group, errp); ++ if (list) { ++ opts = qemu_opts_find(list, id); ++ if (!opts) { ++ error_setg(errp, "there is no %s \"%s\" defined", group, id); ++ return; ++ } ++ qemu_opt_set(opts, arg, str + offset + 1, errp); ++ } + } +- return 0; + } + + static void user_register_global_props(void) +@@ -2752,8 +2788,7 @@ void qemu_init(int argc, char **argv, char **envp) + } + break; + case QEMU_OPTION_set: +- if (qemu_set_option(optarg) != 0) +- exit(1); ++ qemu_set_option(optarg, &error_fatal); + break; + case QEMU_OPTION_global: + if (qemu_global_option(optarg) != 0) +@@ -3385,7 +3420,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); +-- +2.31.1 + diff --git a/0005-vl-plug-object-back-into-readconfig.patch b/0005-vl-plug-object-back-into-readconfig.patch new file mode 100644 index 0000000..f411c49 --- /dev/null +++ b/0005-vl-plug-object-back-into-readconfig.patch @@ -0,0 +1,87 @@ +From 10b889b529490efb228667505bab851e8e406c67 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 18 May 2021 11:40:59 -0400 +Subject: [PATCH 5/5] vl: plug -object back into -readconfig + +Commit bc2f4fcb1d ("qom: move user_creatable_add_opts logic to vl.c +and QAPIfy it", 2021-03-19) switched the creation of objects from +qemu_opts_foreach to a bespoke QTAILQ in preparation for supporting JSON +syntax in -object. + +Unfortunately in doing so it lost support for [object] stanzas in +configuration files and also for "-set object.ID.KEY=VAL". The latter +is hard to re-establish and probably best solved by deprecating -set. +This patch uses the infrastructure introduced by the previous two +patches in order to parse QOM objects correctly from configuration +files. + +Cc: Markus Armbruster +Cc: qemu-stable@nongnu.org +Reviewed-by: Kevin Wolf +Signed-off-by: Paolo Bonzini +Message-Id: <20210524105752.3318299-4-pbonzini@redhat.com> +--- + softmmu/vl.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/softmmu/vl.c b/softmmu/vl.c +index 48d1f06..d282dea 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -1709,9 +1709,15 @@ static void object_option_foreach_add(bool (*type_opt_predicate)(const char *)) + } + } + ++static void object_option_add_visitor(Visitor *v) ++{ ++ ObjectOption *opt = g_new0(ObjectOption, 1); ++ visit_type_ObjectOptions(v, NULL, &opt->opts, &error_fatal); ++ QTAILQ_INSERT_TAIL(&object_opts, opt, next); ++} ++ + static void object_option_parse(const char *optarg) + { +- ObjectOption *opt; + QemuOpts *opts; + const char *type; + Visitor *v; +@@ -1739,11 +1745,8 @@ static void object_option_parse(const char *optarg) + v = opts_visitor_new(opts); + } + +- opt = g_new0(ObjectOption, 1); +- visit_type_ObjectOptions(v, NULL, &opt->opts, &error_fatal); ++ object_option_add_visitor(v); + visit_free(v); +- +- QTAILQ_INSERT_TAIL(&object_opts, opt, next); + } + + /* +@@ -2120,13 +2123,22 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp) + */ + static bool is_qemuopts_group(const char *group) + { ++ if (g_str_equal(group, "object")) { ++ return false; ++ } + return true; + } + + static void qemu_record_config_group(const char *group, QDict *dict, + bool from_json, Error **errp) + { +- abort(); ++ if (g_str_equal(group, "object")) { ++ Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(dict)); ++ object_option_add_visitor(v); ++ visit_free(v); ++ } else { ++ abort(); ++ } + } + + /* +-- +2.31.1 +