blob: 14093ac3a0240df9168701190e0ac4dff394bd34 [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 Wolff3534152020-02-24 15:29:49 +010032#include "crypto/init.h"
33
34#include "qapi/error.h"
Kevin Wolfeed8b692020-02-24 15:29:57 +010035#include "qapi/qapi-commands-block.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010036#include "qapi/qapi-commands-block-core.h"
Kevin Wolfeed8b692020-02-24 15:29:57 +010037#include "qapi/qapi-visit-block.h"
38#include "qapi/qapi-visit-block-core.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010039#include "qapi/qmp/qdict.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010040#include "qapi/qobject-input-visitor.h"
41
Kevin Wolff3534152020-02-24 15:29:49 +010042#include "qemu-common.h"
43#include "qemu-version.h"
44#include "qemu/config-file.h"
45#include "qemu/error-report.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010046#include "qemu/help_option.h"
Kevin Wolff3534152020-02-24 15:29:49 +010047#include "qemu/log.h"
48#include "qemu/main-loop.h"
49#include "qemu/module.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010050#include "qemu/option.h"
51#include "qom/object_interfaces.h"
Kevin Wolff3534152020-02-24 15:29:49 +010052
Kevin Wolfaa706832020-02-24 15:30:00 +010053#include "sysemu/runstate.h"
Kevin Wolff3534152020-02-24 15:29:49 +010054#include "trace/control.h"
55
Kevin Wolfaa706832020-02-24 15:30:00 +010056static volatile bool exit_requested = false;
57
58void qemu_system_killed(int signal, pid_t pid)
59{
60 exit_requested = true;
61}
62
Kevin Wolff3534152020-02-24 15:29:49 +010063static void help(void)
64{
65 printf(
66"Usage: %s [options]\n"
67"QEMU storage daemon\n"
68"\n"
69" -h, --help display this help and exit\n"
70" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
71" specify tracing options\n"
72" -V, --version output version information and exit\n"
73"\n"
Kevin Wolf14837c62020-02-24 15:29:54 +010074" --blockdev [driver=]<driver>[,node-name=<N>][,discard=ignore|unmap]\n"
75" [,cache.direct=on|off][,cache.no-flush=on|off]\n"
76" [,read-only=on|off][,auto-read-only=on|off]\n"
77" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n"
78" [,driver specific parameters...]\n"
79" configure a block backend\n"
80"\n"
Kevin Wolf39411122020-02-24 15:29:59 +010081" --export [type=]nbd,device=<node-name>[,name=<export-name>]\n"
82" [,writable=on|off][,bitmap=<name>]\n"
83" export the specified block node over NBD\n"
84" (requires --nbd-server)\n"
85"\n"
Kevin Wolfeed8b692020-02-24 15:29:57 +010086" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
87" [,tls-creds=<id>][,tls-authz=<id>]\n"
88" --nbd-server addr.type=unix,addr.path=<path>\n"
89" [,tls-creds=<id>][,tls-authz=<id>]\n"
90" start an NBD server for exporting block nodes\n"
91"\n"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010092" --object help list object types that can be added\n"
93" --object <type>,help list properties for the given object type\n"
94" --object <type>[,<property>=<value>...]\n"
95" create a new object of type <type>, setting\n"
96" properties in the order they are specified. Note\n"
97" that the 'id' property must be set.\n"
98" See the qemu(1) man page for documentation of the\n"
99" objects that can be added.\n"
100"\n"
Kevin Wolff3534152020-02-24 15:29:49 +0100101QEMU_HELP_BOTTOM "\n",
102 error_get_progname());
103}
104
Kevin Wolf14837c62020-02-24 15:29:54 +0100105enum {
106 OPTION_BLOCKDEV = 256,
Kevin Wolf39411122020-02-24 15:29:59 +0100107 OPTION_EXPORT,
Kevin Wolfeed8b692020-02-24 15:29:57 +0100108 OPTION_NBD_SERVER,
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100109 OPTION_OBJECT,
110};
111
112static QemuOptsList qemu_object_opts = {
113 .name = "object",
114 .implied_opt_name = "qom-type",
115 .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
116 .desc = {
117 { }
118 },
Kevin Wolf14837c62020-02-24 15:29:54 +0100119};
120
Kevin Wolf39411122020-02-24 15:29:59 +0100121static void init_export(BlockExport *export, Error **errp)
122{
123 switch (export->type) {
124 case BLOCK_EXPORT_TYPE_NBD:
125 qmp_nbd_server_add(&export->u.nbd, errp);
126 break;
127 default:
128 g_assert_not_reached();
129 }
130}
131
Kevin Wolff3534152020-02-24 15:29:49 +0100132static void process_options(int argc, char *argv[])
133{
134 int c;
135
136 static const struct option long_options[] = {
Kevin Wolf14837c62020-02-24 15:29:54 +0100137 {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
Kevin Wolf39411122020-02-24 15:29:59 +0100138 {"export", required_argument, NULL, OPTION_EXPORT},
Kevin Wolff3534152020-02-24 15:29:49 +0100139 {"help", no_argument, NULL, 'h'},
Kevin Wolfeed8b692020-02-24 15:29:57 +0100140 {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100141 {"object", required_argument, NULL, OPTION_OBJECT},
Kevin Wolff3534152020-02-24 15:29:49 +0100142 {"trace", required_argument, NULL, 'T'},
143 {"version", no_argument, NULL, 'V'},
144 {0, 0, 0, 0}
145 };
146
147 /*
148 * In contrast to the system emulator, options are processed in the order
149 * they are given on the command lines. This means that things must be
150 * defined first before they can be referenced in another option.
151 */
152 while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) {
153 switch (c) {
154 case '?':
155 exit(EXIT_FAILURE);
156 case 'h':
157 help();
158 exit(EXIT_SUCCESS);
159 case 'T':
160 {
161 char *trace_file = trace_opt_parse(optarg);
162 trace_init_file(trace_file);
163 g_free(trace_file);
164 break;
165 }
166 case 'V':
167 printf("qemu-storage-daemon version "
168 QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
169 exit(EXIT_SUCCESS);
Kevin Wolf14837c62020-02-24 15:29:54 +0100170 case OPTION_BLOCKDEV:
171 {
172 Visitor *v;
173 BlockdevOptions *options;
174
175 v = qobject_input_visitor_new_str(optarg, "driver",
176 &error_fatal);
177
178 visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
179 visit_free(v);
180
181 qmp_blockdev_add(options, &error_fatal);
182 qapi_free_BlockdevOptions(options);
183 break;
184 }
Kevin Wolf39411122020-02-24 15:29:59 +0100185 case OPTION_EXPORT:
186 {
187 Visitor *v;
188 BlockExport *export;
189
190 v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
191 visit_type_BlockExport(v, NULL, &export, &error_fatal);
192 visit_free(v);
193
194 init_export(export, &error_fatal);
195 qapi_free_BlockExport(export);
196 break;
197 }
Kevin Wolfeed8b692020-02-24 15:29:57 +0100198 case OPTION_NBD_SERVER:
199 {
200 Visitor *v;
201 NbdServerOptions *options;
202
203 v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal);
204 visit_type_NbdServerOptions(v, NULL, &options, &error_fatal);
205 visit_free(v);
206
207 nbd_server_start_options(options, &error_fatal);
208 qapi_free_NbdServerOptions(options);
209 break;
210 }
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100211 case OPTION_OBJECT:
212 {
213 QemuOpts *opts;
214 const char *type;
215 QDict *args;
216 QObject *ret_data = NULL;
217
218 /* FIXME The keyval parser rejects 'help' arguments, so we must
219 * unconditionall try QemuOpts first. */
220 opts = qemu_opts_parse(&qemu_object_opts,
221 optarg, true, &error_fatal);
222 type = qemu_opt_get(opts, "qom-type");
223 if (type && user_creatable_print_help(type, opts)) {
224 exit(EXIT_SUCCESS);
225 }
226 qemu_opts_del(opts);
227
228 args = keyval_parse(optarg, "qom-type", &error_fatal);
229 qmp_object_add(args, &ret_data, &error_fatal);
230 qobject_unref(args);
231 qobject_unref(ret_data);
232 break;
233 }
Kevin Wolff3534152020-02-24 15:29:49 +0100234 default:
235 g_assert_not_reached();
236 }
237 }
238 if (optind != argc) {
239 error_report("Unexpected argument: %s", argv[optind]);
240 exit(EXIT_FAILURE);
241 }
242}
243
244int main(int argc, char *argv[])
245{
246#ifdef CONFIG_POSIX
247 signal(SIGPIPE, SIG_IGN);
248#endif
249
250 error_init(argv[0]);
251 qemu_init_exec_dir(argv[0]);
Kevin Wolfaa706832020-02-24 15:30:00 +0100252 os_setup_signal_handling();
Kevin Wolff3534152020-02-24 15:29:49 +0100253
254 module_call_init(MODULE_INIT_QOM);
255 module_call_init(MODULE_INIT_TRACE);
256 qemu_add_opts(&qemu_trace_opts);
257 qcrypto_init(&error_fatal);
258 bdrv_init();
259
260 if (!trace_init_backends()) {
261 return EXIT_FAILURE;
262 }
263 qemu_set_log(LOG_TRACE);
264
265 qemu_init_main_loop(&error_fatal);
266 process_options(argc, argv);
267
Kevin Wolfaa706832020-02-24 15:30:00 +0100268 while (!exit_requested) {
269 main_loop_wait(false);
270 }
271
Kevin Wolff3534152020-02-24 15:29:49 +0100272 return EXIT_SUCCESS;
273}