blob: 0cd8144c814f4b855be2af2a0390dde9071db126 [file] [log] [blame]
Kevin Wolff3534152020-02-24 15:29:49 +01001/*
2 * QEMU storage daemon
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 * Copyright (c) 2019 Kevin Wolf <kwolf@redhat.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26#include "qemu/osdep.h"
27
28#include <getopt.h>
29
30#include "block/block.h"
31#include "crypto/init.h"
32
33#include "qapi/error.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010034#include "qapi/qapi-visit-block-core.h"
35#include "qapi/qapi-commands-block-core.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010036#include "qapi/qmp/qdict.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010037#include "qapi/qobject-input-visitor.h"
38
Kevin Wolff3534152020-02-24 15:29:49 +010039#include "qemu-common.h"
40#include "qemu-version.h"
41#include "qemu/config-file.h"
42#include "qemu/error-report.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010043#include "qemu/help_option.h"
Kevin Wolff3534152020-02-24 15:29:49 +010044#include "qemu/log.h"
45#include "qemu/main-loop.h"
46#include "qemu/module.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010047#include "qemu/option.h"
48#include "qom/object_interfaces.h"
Kevin Wolff3534152020-02-24 15:29:49 +010049
50#include "trace/control.h"
51
52static void help(void)
53{
54 printf(
55"Usage: %s [options]\n"
56"QEMU storage daemon\n"
57"\n"
58" -h, --help display this help and exit\n"
59" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
60" specify tracing options\n"
61" -V, --version output version information and exit\n"
62"\n"
Kevin Wolf14837c62020-02-24 15:29:54 +010063" --blockdev [driver=]<driver>[,node-name=<N>][,discard=ignore|unmap]\n"
64" [,cache.direct=on|off][,cache.no-flush=on|off]\n"
65" [,read-only=on|off][,auto-read-only=on|off]\n"
66" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n"
67" [,driver specific parameters...]\n"
68" configure a block backend\n"
69"\n"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010070" --object help list object types that can be added\n"
71" --object <type>,help list properties for the given object type\n"
72" --object <type>[,<property>=<value>...]\n"
73" create a new object of type <type>, setting\n"
74" properties in the order they are specified. Note\n"
75" that the 'id' property must be set.\n"
76" See the qemu(1) man page for documentation of the\n"
77" objects that can be added.\n"
78"\n"
Kevin Wolff3534152020-02-24 15:29:49 +010079QEMU_HELP_BOTTOM "\n",
80 error_get_progname());
81}
82
Kevin Wolf14837c62020-02-24 15:29:54 +010083enum {
84 OPTION_BLOCKDEV = 256,
Kevin Wolfd6da78b2020-02-24 15:29:56 +010085 OPTION_OBJECT,
86};
87
88static QemuOptsList qemu_object_opts = {
89 .name = "object",
90 .implied_opt_name = "qom-type",
91 .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
92 .desc = {
93 { }
94 },
Kevin Wolf14837c62020-02-24 15:29:54 +010095};
96
Kevin Wolff3534152020-02-24 15:29:49 +010097static void process_options(int argc, char *argv[])
98{
99 int c;
100
101 static const struct option long_options[] = {
Kevin Wolf14837c62020-02-24 15:29:54 +0100102 {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
Kevin Wolff3534152020-02-24 15:29:49 +0100103 {"help", no_argument, NULL, 'h'},
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100104 {"object", required_argument, NULL, OPTION_OBJECT},
Kevin Wolff3534152020-02-24 15:29:49 +0100105 {"trace", required_argument, NULL, 'T'},
106 {"version", no_argument, NULL, 'V'},
107 {0, 0, 0, 0}
108 };
109
110 /*
111 * In contrast to the system emulator, options are processed in the order
112 * they are given on the command lines. This means that things must be
113 * defined first before they can be referenced in another option.
114 */
115 while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) {
116 switch (c) {
117 case '?':
118 exit(EXIT_FAILURE);
119 case 'h':
120 help();
121 exit(EXIT_SUCCESS);
122 case 'T':
123 {
124 char *trace_file = trace_opt_parse(optarg);
125 trace_init_file(trace_file);
126 g_free(trace_file);
127 break;
128 }
129 case 'V':
130 printf("qemu-storage-daemon version "
131 QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
132 exit(EXIT_SUCCESS);
Kevin Wolf14837c62020-02-24 15:29:54 +0100133 case OPTION_BLOCKDEV:
134 {
135 Visitor *v;
136 BlockdevOptions *options;
137
138 v = qobject_input_visitor_new_str(optarg, "driver",
139 &error_fatal);
140
141 visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
142 visit_free(v);
143
144 qmp_blockdev_add(options, &error_fatal);
145 qapi_free_BlockdevOptions(options);
146 break;
147 }
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100148 case OPTION_OBJECT:
149 {
150 QemuOpts *opts;
151 const char *type;
152 QDict *args;
153 QObject *ret_data = NULL;
154
155 /* FIXME The keyval parser rejects 'help' arguments, so we must
156 * unconditionall try QemuOpts first. */
157 opts = qemu_opts_parse(&qemu_object_opts,
158 optarg, true, &error_fatal);
159 type = qemu_opt_get(opts, "qom-type");
160 if (type && user_creatable_print_help(type, opts)) {
161 exit(EXIT_SUCCESS);
162 }
163 qemu_opts_del(opts);
164
165 args = keyval_parse(optarg, "qom-type", &error_fatal);
166 qmp_object_add(args, &ret_data, &error_fatal);
167 qobject_unref(args);
168 qobject_unref(ret_data);
169 break;
170 }
Kevin Wolff3534152020-02-24 15:29:49 +0100171 default:
172 g_assert_not_reached();
173 }
174 }
175 if (optind != argc) {
176 error_report("Unexpected argument: %s", argv[optind]);
177 exit(EXIT_FAILURE);
178 }
179}
180
181int main(int argc, char *argv[])
182{
183#ifdef CONFIG_POSIX
184 signal(SIGPIPE, SIG_IGN);
185#endif
186
187 error_init(argv[0]);
188 qemu_init_exec_dir(argv[0]);
189
190 module_call_init(MODULE_INIT_QOM);
191 module_call_init(MODULE_INIT_TRACE);
192 qemu_add_opts(&qemu_trace_opts);
193 qcrypto_init(&error_fatal);
194 bdrv_init();
195
196 if (!trace_init_backends()) {
197 return EXIT_FAILURE;
198 }
199 qemu_set_log(LOG_TRACE);
200
201 qemu_init_main_loop(&error_fatal);
202 process_options(argc, argv);
203
204 return EXIT_SUCCESS;
205}