From 7c58bb769dce4764b413ae4a9e13c4c54d537b87 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 4 Aug 2020 20:18:36 +0200 Subject: meson: convert qemu-storage-daemon Signed-off-by: Paolo Bonzini --- Makefile | 5 - Makefile.objs | 10 - meson.build | 2 +- qemu-storage-daemon.c | 343 ----------------------------------- storage-daemon/Makefile.objs | 3 - storage-daemon/meson.build | 13 ++ storage-daemon/qapi/meson.build | 5 +- storage-daemon/qemu-storage-daemon.c | 343 +++++++++++++++++++++++++++++++++++ 8 files changed, 358 insertions(+), 366 deletions(-) delete mode 100644 qemu-storage-daemon.c delete mode 100644 storage-daemon/Makefile.objs create mode 100644 storage-daemon/qemu-storage-daemon.c diff --git a/Makefile b/Makefile index cb364f4..0b06b9c 100644 --- a/Makefile +++ b/Makefile @@ -179,8 +179,6 @@ include $(SRC_PATH)/Makefile.objs endif dummy := $(call unnest-vars,, \ - storage-daemon-obj-y \ - storage-daemon-obj-m \ common-obj-y \ common-obj-m) @@ -196,7 +194,6 @@ TARGET_DIRS_RULES := $(foreach t, all fuzz clean install, $(addsuffix /$(t), $(T SOFTMMU_ALL_RULES=$(filter %-softmmu/all, $(TARGET_DIRS_RULES)) $(SOFTMMU_ALL_RULES): $(authz-obj-y) $(SOFTMMU_ALL_RULES): $(block-obj-y) -$(SOFTMMU_ALL_RULES): $(storage-daemon-obj-y) $(SOFTMMU_ALL_RULES): $(chardev-obj-y) $(SOFTMMU_ALL_RULES): $(crypto-obj-y) $(SOFTMMU_ALL_RULES): $(io-obj-y) @@ -287,8 +284,6 @@ Makefile: $(version-obj-y) COMMON_LDADDS = libqemuutil.a -qemu-storage-daemon$(EXESUF): qemu-storage-daemon.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(chardev-obj-y) $(io-obj-y) $(qom-obj-y) $(storage-daemon-obj-y) $(COMMON_LDADDS) - clean: recurse-clean ninja-clean clean-ctlist -test -f ninjatool && ./ninjatool $(if $(V),-v,) -t clean # avoid old build problems by removing potentially incorrect old files diff --git a/Makefile.objs b/Makefile.objs index d7826c1..e304d92 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -33,16 +33,6 @@ io-obj-y = io/libio.fa endif # CONFIG_SOFTMMU or CONFIG_TOOLS -####################################################################### -# storage-daemon-obj-y is code used by qemu-storage-daemon (these objects are -# used for system emulation, too, but specified separately there) - -storage-daemon-obj-y = block/ qapi/ qom/ storage-daemon/ -storage-daemon-obj-y += blockdev.o blockdev-nbd.o iothread.o job-qmp.o -storage-daemon-obj-$(CONFIG_WIN32) += os-win32.o -storage-daemon-obj-$(CONFIG_POSIX) += os-posix.o -storage-daemon-obj-y += libqmp.fa - ###################################################################### # Target independent part of system emulation. The long term path is to # suppress *all* target specific code in case of system emulation, i.e. a diff --git a/meson.build b/meson.build index 9d1a530..4ff3f7b 100644 --- a/meson.build +++ b/meson.build @@ -590,7 +590,6 @@ subdir('util') subdir('qom') subdir('authz') subdir('crypto') -subdir('storage-daemon') subdir('ui') @@ -800,6 +799,7 @@ if have_tools dependencies: [block, qemuutil], install: true) endif + subdir('storage-daemon') subdir('contrib/rdmacm-mux') subdir('contrib/elf2dmp') diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c deleted file mode 100644 index 7e9b0e0..0000000 --- a/qemu-storage-daemon.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * QEMU storage daemon - * - * Copyright (c) 2003-2008 Fabrice Bellard - * Copyright (c) 2019 Kevin Wolf - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" - -#include - -#include "block/block.h" -#include "block/nbd.h" -#include "chardev/char.h" -#include "crypto/init.h" -#include "monitor/monitor.h" -#include "monitor/monitor-internal.h" - -#include "qapi/error.h" -#include "qapi/qapi-visit-block.h" -#include "qapi/qapi-visit-block-core.h" -#include "qapi/qapi-visit-control.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qstring.h" -#include "qapi/qobject-input-visitor.h" - -#include "qemu-common.h" -#include "qemu-version.h" -#include "qemu/config-file.h" -#include "qemu/error-report.h" -#include "qemu/help_option.h" -#include "qemu/log.h" -#include "qemu/main-loop.h" -#include "qemu/module.h" -#include "qemu/option.h" -#include "qom/object_interfaces.h" - -#include "storage-daemon/qapi/qapi-commands.h" -#include "storage-daemon/qapi/qapi-init-commands.h" - -#include "sysemu/runstate.h" -#include "trace/control.h" - -static volatile bool exit_requested = false; - -void qemu_system_killed(int signal, pid_t pid) -{ - exit_requested = true; -} - -void qmp_quit(Error **errp) -{ - exit_requested = true; -} - -static void help(void) -{ - printf( -"Usage: %s [options]\n" -"QEMU storage daemon\n" -"\n" -" -h, --help display this help and exit\n" -" -T, --trace [[enable=]][,events=][,file=]\n" -" specify tracing options\n" -" -V, --version output version information and exit\n" -"\n" -" --blockdev [driver=][,node-name=][,discard=ignore|unmap]\n" -" [,cache.direct=on|off][,cache.no-flush=on|off]\n" -" [,read-only=on|off][,auto-read-only=on|off]\n" -" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n" -" [,driver specific parameters...]\n" -" configure a block backend\n" -"\n" -" --chardev configure a character device backend\n" -" (see the qemu(1) man page for possible options)\n" -"\n" -" --export [type=]nbd,device=[,name=]\n" -" [,writable=on|off][,bitmap=]\n" -" export the specified block node over NBD\n" -" (requires --nbd-server)\n" -"\n" -" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n" -" configure a QMP monitor\n" -"\n" -" --nbd-server addr.type=inet,addr.host=,addr.port=\n" -" [,tls-creds=][,tls-authz=]\n" -" --nbd-server addr.type=unix,addr.path=\n" -" [,tls-creds=][,tls-authz=]\n" -" start an NBD server for exporting block nodes\n" -"\n" -" --object help list object types that can be added\n" -" --object ,help list properties for the given object type\n" -" --object [,=...]\n" -" create a new object of type , setting\n" -" properties in the order they are specified. Note\n" -" that the 'id' property must be set.\n" -" See the qemu(1) man page for documentation of the\n" -" objects that can be added.\n" -"\n" -QEMU_HELP_BOTTOM "\n", - error_get_progname()); -} - -enum { - OPTION_BLOCKDEV = 256, - OPTION_CHARDEV, - OPTION_EXPORT, - OPTION_MONITOR, - OPTION_NBD_SERVER, - OPTION_OBJECT, -}; - -extern QemuOptsList qemu_chardev_opts; - -static QemuOptsList qemu_object_opts = { - .name = "object", - .implied_opt_name = "qom-type", - .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head), - .desc = { - { } - }, -}; - -static void init_qmp_commands(void) -{ - qmp_init_marshal(&qmp_commands); - qmp_register_command(&qmp_commands, "query-qmp-schema", - qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); - - QTAILQ_INIT(&qmp_cap_negotiation_commands); - qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", - qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG); -} - -static void init_export(BlockExport *export, Error **errp) -{ - switch (export->type) { - case BLOCK_EXPORT_TYPE_NBD: - qmp_nbd_server_add(&export->u.nbd, errp); - break; - default: - g_assert_not_reached(); - } -} - -static void process_options(int argc, char *argv[]) -{ - int c; - - static const struct option long_options[] = { - {"blockdev", required_argument, NULL, OPTION_BLOCKDEV}, - {"chardev", required_argument, NULL, OPTION_CHARDEV}, - {"export", required_argument, NULL, OPTION_EXPORT}, - {"help", no_argument, NULL, 'h'}, - {"monitor", required_argument, NULL, OPTION_MONITOR}, - {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER}, - {"object", required_argument, NULL, OPTION_OBJECT}, - {"trace", required_argument, NULL, 'T'}, - {"version", no_argument, NULL, 'V'}, - {0, 0, 0, 0} - }; - - /* - * In contrast to the system emulator, options are processed in the order - * they are given on the command lines. This means that things must be - * defined first before they can be referenced in another option. - */ - while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) { - switch (c) { - case '?': - exit(EXIT_FAILURE); - case 'h': - help(); - exit(EXIT_SUCCESS); - case 'T': - { - char *trace_file = trace_opt_parse(optarg); - trace_init_file(trace_file); - g_free(trace_file); - break; - } - case 'V': - printf("qemu-storage-daemon version " - QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n"); - exit(EXIT_SUCCESS); - case OPTION_BLOCKDEV: - { - Visitor *v; - BlockdevOptions *options; - - v = qobject_input_visitor_new_str(optarg, "driver", - &error_fatal); - - visit_type_BlockdevOptions(v, NULL, &options, &error_fatal); - visit_free(v); - - qmp_blockdev_add(options, &error_fatal); - qapi_free_BlockdevOptions(options); - break; - } - case OPTION_CHARDEV: - { - /* TODO This interface is not stable until we QAPIfy it */ - QemuOpts *opts = qemu_opts_parse_noisily(&qemu_chardev_opts, - optarg, true); - if (opts == NULL) { - exit(EXIT_FAILURE); - } - - if (!qemu_chr_new_from_opts(opts, NULL, &error_fatal)) { - /* No error, but NULL returned means help was printed */ - exit(EXIT_SUCCESS); - } - qemu_opts_del(opts); - break; - } - case OPTION_EXPORT: - { - Visitor *v; - BlockExport *export; - - v = qobject_input_visitor_new_str(optarg, "type", &error_fatal); - visit_type_BlockExport(v, NULL, &export, &error_fatal); - visit_free(v); - - init_export(export, &error_fatal); - qapi_free_BlockExport(export); - break; - } - case OPTION_MONITOR: - { - Visitor *v; - MonitorOptions *monitor; - - v = qobject_input_visitor_new_str(optarg, "chardev", - &error_fatal); - visit_type_MonitorOptions(v, NULL, &monitor, &error_fatal); - visit_free(v); - - /* TODO Catch duplicate monitor IDs */ - monitor_init(monitor, false, &error_fatal); - qapi_free_MonitorOptions(monitor); - break; - } - case OPTION_NBD_SERVER: - { - Visitor *v; - NbdServerOptions *options; - - v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal); - visit_type_NbdServerOptions(v, NULL, &options, &error_fatal); - visit_free(v); - - nbd_server_start_options(options, &error_fatal); - qapi_free_NbdServerOptions(options); - break; - } - case OPTION_OBJECT: - { - QemuOpts *opts; - const char *type; - QDict *args; - - /* FIXME The keyval parser rejects 'help' arguments, so we must - * unconditionall try QemuOpts first. */ - opts = qemu_opts_parse(&qemu_object_opts, - optarg, true, &error_fatal); - type = qemu_opt_get(opts, "qom-type"); - if (type && user_creatable_print_help(type, opts)) { - exit(EXIT_SUCCESS); - } - qemu_opts_del(opts); - - args = keyval_parse(optarg, "qom-type", &error_fatal); - user_creatable_add_dict(args, true, &error_fatal); - qobject_unref(args); - break; - } - default: - g_assert_not_reached(); - } - } - if (optind != argc) { - error_report("Unexpected argument: %s", argv[optind]); - exit(EXIT_FAILURE); - } -} - -int main(int argc, char *argv[]) -{ -#ifdef CONFIG_POSIX - signal(SIGPIPE, SIG_IGN); -#endif - - error_init(argv[0]); - qemu_init_exec_dir(argv[0]); - os_setup_signal_handling(); - - module_call_init(MODULE_INIT_QOM); - module_call_init(MODULE_INIT_TRACE); - qemu_add_opts(&qemu_object_opts); - qemu_add_opts(&qemu_trace_opts); - qcrypto_init(&error_fatal); - bdrv_init(); - monitor_init_globals_core(); - init_qmp_commands(); - - if (!trace_init_backends()) { - return EXIT_FAILURE; - } - qemu_set_log(LOG_TRACE); - - qemu_init_main_loop(&error_fatal); - process_options(argc, argv); - - while (!exit_requested) { - main_loop_wait(false); - } - - monitor_cleanup(); - qemu_chr_cleanup(); - user_creatable_cleanup(); - - return EXIT_SUCCESS; -} diff --git a/storage-daemon/Makefile.objs b/storage-daemon/Makefile.objs deleted file mode 100644 index 41c0d02..0000000 --- a/storage-daemon/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -storage-daemon-obj-y = qapi/libqsd-qapi.fa - -qemu-storage-daemon.o: storage-daemon/qapi/qapi-commands.h storage-daemon/qapi/qapi-init-commands.h diff --git a/storage-daemon/meson.build b/storage-daemon/meson.build index 35f8949..0409acc 100644 --- a/storage-daemon/meson.build +++ b/storage-daemon/meson.build @@ -1 +1,14 @@ +qsd_ss = ss.source_set() +qsd_ss.add(files('qemu-storage-daemon.c')) +qsd_ss.add(block, chardev, qmp, qom, qemuutil) +qsd_ss.add_all(blockdev_ss) + subdir('qapi') + +if have_tools + qsd_ss = qsd_ss.apply(config_host, strict: false) + executable('qemu-storage-daemon', + qsd_ss.sources(), + dependencies: qsd_ss.dependencies(), + install: true) +endif diff --git a/storage-daemon/qapi/meson.build b/storage-daemon/qapi/meson.build index 7a2b041..cea618b 100644 --- a/storage-daemon/qapi/meson.build +++ b/storage-daemon/qapi/meson.build @@ -4,7 +4,4 @@ qsd_qapi_files = custom_target('QAPI files for qemu-storage-daemon', command: [ qapi_gen, '-o', 'storage-daemon/qapi', '@INPUT@' ], depend_files: [ qapi_inputs, qapi_gen_depends ]) -static_library('qsd-qapi', - qsd_qapi_files.to_list(), - name_suffix: 'fa', - build_by_default: false) +qsd_ss.add(qsd_qapi_files.to_list()) diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c new file mode 100644 index 0000000..7e9b0e0 --- /dev/null +++ b/storage-daemon/qemu-storage-daemon.c @@ -0,0 +1,343 @@ +/* + * QEMU storage daemon + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2019 Kevin Wolf + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" + +#include + +#include "block/block.h" +#include "block/nbd.h" +#include "chardev/char.h" +#include "crypto/init.h" +#include "monitor/monitor.h" +#include "monitor/monitor-internal.h" + +#include "qapi/error.h" +#include "qapi/qapi-visit-block.h" +#include "qapi/qapi-visit-block-core.h" +#include "qapi/qapi-visit-control.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qobject-input-visitor.h" + +#include "qemu-common.h" +#include "qemu-version.h" +#include "qemu/config-file.h" +#include "qemu/error-report.h" +#include "qemu/help_option.h" +#include "qemu/log.h" +#include "qemu/main-loop.h" +#include "qemu/module.h" +#include "qemu/option.h" +#include "qom/object_interfaces.h" + +#include "storage-daemon/qapi/qapi-commands.h" +#include "storage-daemon/qapi/qapi-init-commands.h" + +#include "sysemu/runstate.h" +#include "trace/control.h" + +static volatile bool exit_requested = false; + +void qemu_system_killed(int signal, pid_t pid) +{ + exit_requested = true; +} + +void qmp_quit(Error **errp) +{ + exit_requested = true; +} + +static void help(void) +{ + printf( +"Usage: %s [options]\n" +"QEMU storage daemon\n" +"\n" +" -h, --help display this help and exit\n" +" -T, --trace [[enable=]][,events=][,file=]\n" +" specify tracing options\n" +" -V, --version output version information and exit\n" +"\n" +" --blockdev [driver=][,node-name=][,discard=ignore|unmap]\n" +" [,cache.direct=on|off][,cache.no-flush=on|off]\n" +" [,read-only=on|off][,auto-read-only=on|off]\n" +" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n" +" [,driver specific parameters...]\n" +" configure a block backend\n" +"\n" +" --chardev configure a character device backend\n" +" (see the qemu(1) man page for possible options)\n" +"\n" +" --export [type=]nbd,device=[,name=]\n" +" [,writable=on|off][,bitmap=]\n" +" export the specified block node over NBD\n" +" (requires --nbd-server)\n" +"\n" +" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n" +" configure a QMP monitor\n" +"\n" +" --nbd-server addr.type=inet,addr.host=,addr.port=\n" +" [,tls-creds=][,tls-authz=]\n" +" --nbd-server addr.type=unix,addr.path=\n" +" [,tls-creds=][,tls-authz=]\n" +" start an NBD server for exporting block nodes\n" +"\n" +" --object help list object types that can be added\n" +" --object ,help list properties for the given object type\n" +" --object [,=...]\n" +" create a new object of type , setting\n" +" properties in the order they are specified. Note\n" +" that the 'id' property must be set.\n" +" See the qemu(1) man page for documentation of the\n" +" objects that can be added.\n" +"\n" +QEMU_HELP_BOTTOM "\n", + error_get_progname()); +} + +enum { + OPTION_BLOCKDEV = 256, + OPTION_CHARDEV, + OPTION_EXPORT, + OPTION_MONITOR, + OPTION_NBD_SERVER, + OPTION_OBJECT, +}; + +extern QemuOptsList qemu_chardev_opts; + +static QemuOptsList qemu_object_opts = { + .name = "object", + .implied_opt_name = "qom-type", + .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head), + .desc = { + { } + }, +}; + +static void init_qmp_commands(void) +{ + qmp_init_marshal(&qmp_commands); + qmp_register_command(&qmp_commands, "query-qmp-schema", + qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); + + QTAILQ_INIT(&qmp_cap_negotiation_commands); + qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", + qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG); +} + +static void init_export(BlockExport *export, Error **errp) +{ + switch (export->type) { + case BLOCK_EXPORT_TYPE_NBD: + qmp_nbd_server_add(&export->u.nbd, errp); + break; + default: + g_assert_not_reached(); + } +} + +static void process_options(int argc, char *argv[]) +{ + int c; + + static const struct option long_options[] = { + {"blockdev", required_argument, NULL, OPTION_BLOCKDEV}, + {"chardev", required_argument, NULL, OPTION_CHARDEV}, + {"export", required_argument, NULL, OPTION_EXPORT}, + {"help", no_argument, NULL, 'h'}, + {"monitor", required_argument, NULL, OPTION_MONITOR}, + {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER}, + {"object", required_argument, NULL, OPTION_OBJECT}, + {"trace", required_argument, NULL, 'T'}, + {"version", no_argument, NULL, 'V'}, + {0, 0, 0, 0} + }; + + /* + * In contrast to the system emulator, options are processed in the order + * they are given on the command lines. This means that things must be + * defined first before they can be referenced in another option. + */ + while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) { + switch (c) { + case '?': + exit(EXIT_FAILURE); + case 'h': + help(); + exit(EXIT_SUCCESS); + case 'T': + { + char *trace_file = trace_opt_parse(optarg); + trace_init_file(trace_file); + g_free(trace_file); + break; + } + case 'V': + printf("qemu-storage-daemon version " + QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n"); + exit(EXIT_SUCCESS); + case OPTION_BLOCKDEV: + { + Visitor *v; + BlockdevOptions *options; + + v = qobject_input_visitor_new_str(optarg, "driver", + &error_fatal); + + visit_type_BlockdevOptions(v, NULL, &options, &error_fatal); + visit_free(v); + + qmp_blockdev_add(options, &error_fatal); + qapi_free_BlockdevOptions(options); + break; + } + case OPTION_CHARDEV: + { + /* TODO This interface is not stable until we QAPIfy it */ + QemuOpts *opts = qemu_opts_parse_noisily(&qemu_chardev_opts, + optarg, true); + if (opts == NULL) { + exit(EXIT_FAILURE); + } + + if (!qemu_chr_new_from_opts(opts, NULL, &error_fatal)) { + /* No error, but NULL returned means help was printed */ + exit(EXIT_SUCCESS); + } + qemu_opts_del(opts); + break; + } + case OPTION_EXPORT: + { + Visitor *v; + BlockExport *export; + + v = qobject_input_visitor_new_str(optarg, "type", &error_fatal); + visit_type_BlockExport(v, NULL, &export, &error_fatal); + visit_free(v); + + init_export(export, &error_fatal); + qapi_free_BlockExport(export); + break; + } + case OPTION_MONITOR: + { + Visitor *v; + MonitorOptions *monitor; + + v = qobject_input_visitor_new_str(optarg, "chardev", + &error_fatal); + visit_type_MonitorOptions(v, NULL, &monitor, &error_fatal); + visit_free(v); + + /* TODO Catch duplicate monitor IDs */ + monitor_init(monitor, false, &error_fatal); + qapi_free_MonitorOptions(monitor); + break; + } + case OPTION_NBD_SERVER: + { + Visitor *v; + NbdServerOptions *options; + + v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal); + visit_type_NbdServerOptions(v, NULL, &options, &error_fatal); + visit_free(v); + + nbd_server_start_options(options, &error_fatal); + qapi_free_NbdServerOptions(options); + break; + } + case OPTION_OBJECT: + { + QemuOpts *opts; + const char *type; + QDict *args; + + /* FIXME The keyval parser rejects 'help' arguments, so we must + * unconditionall try QemuOpts first. */ + opts = qemu_opts_parse(&qemu_object_opts, + optarg, true, &error_fatal); + type = qemu_opt_get(opts, "qom-type"); + if (type && user_creatable_print_help(type, opts)) { + exit(EXIT_SUCCESS); + } + qemu_opts_del(opts); + + args = keyval_parse(optarg, "qom-type", &error_fatal); + user_creatable_add_dict(args, true, &error_fatal); + qobject_unref(args); + break; + } + default: + g_assert_not_reached(); + } + } + if (optind != argc) { + error_report("Unexpected argument: %s", argv[optind]); + exit(EXIT_FAILURE); + } +} + +int main(int argc, char *argv[]) +{ +#ifdef CONFIG_POSIX + signal(SIGPIPE, SIG_IGN); +#endif + + error_init(argv[0]); + qemu_init_exec_dir(argv[0]); + os_setup_signal_handling(); + + module_call_init(MODULE_INIT_QOM); + module_call_init(MODULE_INIT_TRACE); + qemu_add_opts(&qemu_object_opts); + qemu_add_opts(&qemu_trace_opts); + qcrypto_init(&error_fatal); + bdrv_init(); + monitor_init_globals_core(); + init_qmp_commands(); + + if (!trace_init_backends()) { + return EXIT_FAILURE; + } + qemu_set_log(LOG_TRACE); + + qemu_init_main_loop(&error_fatal); + process_options(argc, argv); + + while (!exit_requested) { + main_loop_wait(false); + } + + monitor_cleanup(); + qemu_chr_cleanup(); + user_creatable_cleanup(); + + return EXIT_SUCCESS; +} -- cgit v1.1