blob: 82fe6cd5f21cc2dbb52a61d87f5555a3193f50f8 [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"
Kevin Wolfeed8b692020-02-24 15:29:57 +010031#include "block/nbd.h"
Kevin Wolf5e6911c2020-02-24 15:30:01 +010032#include "chardev/char.h"
Kevin Wolff3534152020-02-24 15:29:49 +010033#include "crypto/init.h"
34
35#include "qapi/error.h"
Kevin Wolfeed8b692020-02-24 15:29:57 +010036#include "qapi/qapi-commands-block.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010037#include "qapi/qapi-commands-block-core.h"
Kevin Wolfeed8b692020-02-24 15:29:57 +010038#include "qapi/qapi-visit-block.h"
39#include "qapi/qapi-visit-block-core.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010040#include "qapi/qmp/qdict.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010041#include "qapi/qobject-input-visitor.h"
42
Kevin Wolff3534152020-02-24 15:29:49 +010043#include "qemu-common.h"
44#include "qemu-version.h"
45#include "qemu/config-file.h"
46#include "qemu/error-report.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010047#include "qemu/help_option.h"
Kevin Wolff3534152020-02-24 15:29:49 +010048#include "qemu/log.h"
49#include "qemu/main-loop.h"
50#include "qemu/module.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010051#include "qemu/option.h"
52#include "qom/object_interfaces.h"
Kevin Wolff3534152020-02-24 15:29:49 +010053
Kevin Wolfaa706832020-02-24 15:30:00 +010054#include "sysemu/runstate.h"
Kevin Wolff3534152020-02-24 15:29:49 +010055#include "trace/control.h"
56
Kevin Wolfaa706832020-02-24 15:30:00 +010057static volatile bool exit_requested = false;
58
59void qemu_system_killed(int signal, pid_t pid)
60{
61 exit_requested = true;
62}
63
Kevin Wolff3534152020-02-24 15:29:49 +010064static void help(void)
65{
66 printf(
67"Usage: %s [options]\n"
68"QEMU storage daemon\n"
69"\n"
70" -h, --help display this help and exit\n"
71" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
72" specify tracing options\n"
73" -V, --version output version information and exit\n"
74"\n"
Kevin Wolf14837c62020-02-24 15:29:54 +010075" --blockdev [driver=]<driver>[,node-name=<N>][,discard=ignore|unmap]\n"
76" [,cache.direct=on|off][,cache.no-flush=on|off]\n"
77" [,read-only=on|off][,auto-read-only=on|off]\n"
78" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n"
79" [,driver specific parameters...]\n"
80" configure a block backend\n"
81"\n"
Kevin Wolf5e6911c2020-02-24 15:30:01 +010082" --chardev <options> configure a character device backend\n"
83" (see the qemu(1) man page for possible options)\n"
84"\n"
Kevin Wolf39411122020-02-24 15:29:59 +010085" --export [type=]nbd,device=<node-name>[,name=<export-name>]\n"
86" [,writable=on|off][,bitmap=<name>]\n"
87" export the specified block node over NBD\n"
88" (requires --nbd-server)\n"
89"\n"
Kevin Wolfeed8b692020-02-24 15:29:57 +010090" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
91" [,tls-creds=<id>][,tls-authz=<id>]\n"
92" --nbd-server addr.type=unix,addr.path=<path>\n"
93" [,tls-creds=<id>][,tls-authz=<id>]\n"
94" start an NBD server for exporting block nodes\n"
95"\n"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010096" --object help list object types that can be added\n"
97" --object <type>,help list properties for the given object type\n"
98" --object <type>[,<property>=<value>...]\n"
99" create a new object of type <type>, setting\n"
100" properties in the order they are specified. Note\n"
101" that the 'id' property must be set.\n"
102" See the qemu(1) man page for documentation of the\n"
103" objects that can be added.\n"
104"\n"
Kevin Wolff3534152020-02-24 15:29:49 +0100105QEMU_HELP_BOTTOM "\n",
106 error_get_progname());
107}
108
Kevin Wolf14837c62020-02-24 15:29:54 +0100109enum {
110 OPTION_BLOCKDEV = 256,
Kevin Wolf5e6911c2020-02-24 15:30:01 +0100111 OPTION_CHARDEV,
Kevin Wolf39411122020-02-24 15:29:59 +0100112 OPTION_EXPORT,
Kevin Wolfeed8b692020-02-24 15:29:57 +0100113 OPTION_NBD_SERVER,
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100114 OPTION_OBJECT,
115};
116
Kevin Wolf5e6911c2020-02-24 15:30:01 +0100117extern QemuOptsList qemu_chardev_opts;
118
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100119static QemuOptsList qemu_object_opts = {
120 .name = "object",
121 .implied_opt_name = "qom-type",
122 .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
123 .desc = {
124 { }
125 },
Kevin Wolf14837c62020-02-24 15:29:54 +0100126};
127
Kevin Wolf39411122020-02-24 15:29:59 +0100128static void init_export(BlockExport *export, Error **errp)
129{
130 switch (export->type) {
131 case BLOCK_EXPORT_TYPE_NBD:
132 qmp_nbd_server_add(&export->u.nbd, errp);
133 break;
134 default:
135 g_assert_not_reached();
136 }
137}
138
Kevin Wolff3534152020-02-24 15:29:49 +0100139static void process_options(int argc, char *argv[])
140{
141 int c;
142
143 static const struct option long_options[] = {
Kevin Wolf14837c62020-02-24 15:29:54 +0100144 {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
Kevin Wolf5e6911c2020-02-24 15:30:01 +0100145 {"chardev", required_argument, NULL, OPTION_CHARDEV},
Kevin Wolf39411122020-02-24 15:29:59 +0100146 {"export", required_argument, NULL, OPTION_EXPORT},
Kevin Wolff3534152020-02-24 15:29:49 +0100147 {"help", no_argument, NULL, 'h'},
Kevin Wolfeed8b692020-02-24 15:29:57 +0100148 {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100149 {"object", required_argument, NULL, OPTION_OBJECT},
Kevin Wolff3534152020-02-24 15:29:49 +0100150 {"trace", required_argument, NULL, 'T'},
151 {"version", no_argument, NULL, 'V'},
152 {0, 0, 0, 0}
153 };
154
155 /*
156 * In contrast to the system emulator, options are processed in the order
157 * they are given on the command lines. This means that things must be
158 * defined first before they can be referenced in another option.
159 */
160 while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) {
161 switch (c) {
162 case '?':
163 exit(EXIT_FAILURE);
164 case 'h':
165 help();
166 exit(EXIT_SUCCESS);
167 case 'T':
168 {
169 char *trace_file = trace_opt_parse(optarg);
170 trace_init_file(trace_file);
171 g_free(trace_file);
172 break;
173 }
174 case 'V':
175 printf("qemu-storage-daemon version "
176 QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
177 exit(EXIT_SUCCESS);
Kevin Wolf14837c62020-02-24 15:29:54 +0100178 case OPTION_BLOCKDEV:
179 {
180 Visitor *v;
181 BlockdevOptions *options;
182
183 v = qobject_input_visitor_new_str(optarg, "driver",
184 &error_fatal);
185
186 visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
187 visit_free(v);
188
189 qmp_blockdev_add(options, &error_fatal);
190 qapi_free_BlockdevOptions(options);
191 break;
192 }
Kevin Wolf5e6911c2020-02-24 15:30:01 +0100193 case OPTION_CHARDEV:
194 {
195 /* TODO This interface is not stable until we QAPIfy it */
196 QemuOpts *opts = qemu_opts_parse_noisily(&qemu_chardev_opts,
197 optarg, true);
198 if (opts == NULL) {
199 exit(EXIT_FAILURE);
200 }
201
202 if (!qemu_chr_new_from_opts(opts, NULL, &error_fatal)) {
203 /* No error, but NULL returned means help was printed */
204 exit(EXIT_SUCCESS);
205 }
206 qemu_opts_del(opts);
207 break;
208 }
Kevin Wolf39411122020-02-24 15:29:59 +0100209 case OPTION_EXPORT:
210 {
211 Visitor *v;
212 BlockExport *export;
213
214 v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
215 visit_type_BlockExport(v, NULL, &export, &error_fatal);
216 visit_free(v);
217
218 init_export(export, &error_fatal);
219 qapi_free_BlockExport(export);
220 break;
221 }
Kevin Wolfeed8b692020-02-24 15:29:57 +0100222 case OPTION_NBD_SERVER:
223 {
224 Visitor *v;
225 NbdServerOptions *options;
226
227 v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal);
228 visit_type_NbdServerOptions(v, NULL, &options, &error_fatal);
229 visit_free(v);
230
231 nbd_server_start_options(options, &error_fatal);
232 qapi_free_NbdServerOptions(options);
233 break;
234 }
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100235 case OPTION_OBJECT:
236 {
237 QemuOpts *opts;
238 const char *type;
239 QDict *args;
240 QObject *ret_data = NULL;
241
242 /* FIXME The keyval parser rejects 'help' arguments, so we must
243 * unconditionall try QemuOpts first. */
244 opts = qemu_opts_parse(&qemu_object_opts,
245 optarg, true, &error_fatal);
246 type = qemu_opt_get(opts, "qom-type");
247 if (type && user_creatable_print_help(type, opts)) {
248 exit(EXIT_SUCCESS);
249 }
250 qemu_opts_del(opts);
251
252 args = keyval_parse(optarg, "qom-type", &error_fatal);
253 qmp_object_add(args, &ret_data, &error_fatal);
254 qobject_unref(args);
255 qobject_unref(ret_data);
256 break;
257 }
Kevin Wolff3534152020-02-24 15:29:49 +0100258 default:
259 g_assert_not_reached();
260 }
261 }
262 if (optind != argc) {
263 error_report("Unexpected argument: %s", argv[optind]);
264 exit(EXIT_FAILURE);
265 }
266}
267
268int main(int argc, char *argv[])
269{
270#ifdef CONFIG_POSIX
271 signal(SIGPIPE, SIG_IGN);
272#endif
273
274 error_init(argv[0]);
275 qemu_init_exec_dir(argv[0]);
Kevin Wolfaa706832020-02-24 15:30:00 +0100276 os_setup_signal_handling();
Kevin Wolff3534152020-02-24 15:29:49 +0100277
278 module_call_init(MODULE_INIT_QOM);
279 module_call_init(MODULE_INIT_TRACE);
280 qemu_add_opts(&qemu_trace_opts);
281 qcrypto_init(&error_fatal);
282 bdrv_init();
283
284 if (!trace_init_backends()) {
285 return EXIT_FAILURE;
286 }
287 qemu_set_log(LOG_TRACE);
288
289 qemu_init_main_loop(&error_fatal);
290 process_options(argc, argv);
291
Kevin Wolfaa706832020-02-24 15:30:00 +0100292 while (!exit_requested) {
293 main_loop_wait(false);
294 }
295
Kevin Wolff3534152020-02-24 15:29:49 +0100296 return EXIT_SUCCESS;
297}