1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "qemu/osdep.h"
27
28#include <getopt.h>
29
30#include "block/block.h"
31#include "block/nbd.h"
32#include "chardev/char.h"
33#include "crypto/init.h"
34#include "monitor/monitor.h"
35#include "monitor/monitor-internal.h"
36
37#include "qapi/error.h"
38#include "qapi/qapi-visit-block-core.h"
39#include "qapi/qapi-visit-block-export.h"
40#include "qapi/qapi-visit-control.h"
41#include "qapi/qmp/qdict.h"
42#include "qapi/qmp/qstring.h"
43#include "qapi/qobject-input-visitor.h"
44
45#include "qemu-common.h"
46#include "qemu-version.h"
47#include "qemu/config-file.h"
48#include "qemu/error-report.h"
49#include "qemu/help_option.h"
50#include "qemu/log.h"
51#include "qemu/main-loop.h"
52#include "qemu/module.h"
53#include "qemu/option.h"
54#include "qom/object_interfaces.h"
55
56#include "storage-daemon/qapi/qapi-commands.h"
57#include "storage-daemon/qapi/qapi-init-commands.h"
58
59#include "sysemu/runstate.h"
60#include "trace/control.h"
61
62static const char *pid_file;
63static volatile bool exit_requested = false;
64
65void qemu_system_killed(int signal, pid_t pid)
66{
67 exit_requested = true;
68}
69
70void qmp_quit(Error **errp)
71{
72 exit_requested = true;
73}
74
75static void help(void)
76{
77 printf(
78"Usage: %s [options]\n"
79"QEMU storage daemon\n"
80"\n"
81" -h, --help display this help and exit\n"
82" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
83" specify tracing options\n"
84" -V, --version output version information and exit\n"
85"\n"
86" --blockdev [driver=]<driver>[,node-name=<N>][,discard=ignore|unmap]\n"
87" [,cache.direct=on|off][,cache.no-flush=on|off]\n"
88" [,read-only=on|off][,auto-read-only=on|off]\n"
89" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n"
90" [,driver specific parameters...]\n"
91" configure a block backend\n"
92"\n"
93" --chardev <options> configure a character device backend\n"
94" (see the qemu(1) man page for possible options)\n"
95"\n"
96" --export [type=]nbd,id=<id>,node-name=<node-name>[,name=<export-name>]\n"
97" [,writable=on|off][,bitmap=<name>]\n"
98" export the specified block node over NBD\n"
99" (requires --nbd-server)\n"
100"\n"
101#ifdef CONFIG_FUSE
102" --export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>\n"
103" [,growable=on|off][,writable=on|off]\n"
104" export the specified block node over FUSE\n"
105"\n"
106#endif
107" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
108" configure a QMP monitor\n"
109"\n"
110" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
111" [,tls-creds=<id>][,tls-authz=<id>][,max-connections=<n>]\n"
112" --nbd-server addr.type=unix,addr.path=<path>\n"
113" [,tls-creds=<id>][,tls-authz=<id>][,max-connections=<n>]\n"
114" start an NBD server for exporting block nodes\n"
115"\n"
116" --object help list object types that can be added\n"
117" --object <type>,help list properties for the given object type\n"
118" --object <type>[,<property>=<value>...]\n"
119" create a new object of type <type>, setting\n"
120" properties in the order they are specified. Note\n"
121" that the 'id' property must be set.\n"
122" See the qemu(1) man page for documentation of the\n"
123" objects that can be added.\n"
124"\n"
125" --pidfile <path> write process ID to a file after startup\n"
126"\n"
127QEMU_HELP_BOTTOM "\n",
128 error_get_progname());
129}
130
131enum {
132 OPTION_BLOCKDEV = 256,
133 OPTION_CHARDEV,
134 OPTION_EXPORT,
135 OPTION_MONITOR,
136 OPTION_NBD_SERVER,
137 OPTION_OBJECT,
138 OPTION_PIDFILE,
139};
140
141extern QemuOptsList qemu_chardev_opts;
142
143static void init_qmp_commands(void)
144{
145 qmp_init_marshal(&qmp_commands);
146
147 QTAILQ_INIT(&qmp_cap_negotiation_commands);
148 qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
149 qmp_marshal_qmp_capabilities,
150 QCO_ALLOW_PRECONFIG, 0);
151}
152
153static int getopt_set_loc(int argc, char **argv, const char *optstring,
154 const struct option *longopts)
155{
156 int c, save_index;
157
158 optarg = NULL;
159 save_index = optind;
160 c = getopt_long(argc, argv, optstring, longopts, NULL);
161 if (optarg) {
162 loc_set_cmdline(argv, save_index, MAX(1, optind - save_index));
163 }
164 return c;
165}
166
167static void process_options(int argc, char *argv[])
168{
169 int c;
170
171 static const struct option long_options[] = {
172 {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
173 {"chardev", required_argument, NULL, OPTION_CHARDEV},
174 {"export", required_argument, NULL, OPTION_EXPORT},
175 {"help", no_argument, NULL, 'h'},
176 {"monitor", required_argument, NULL, OPTION_MONITOR},
177 {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
178 {"object", required_argument, NULL, OPTION_OBJECT},
179 {"pidfile", required_argument, NULL, OPTION_PIDFILE},
180 {"trace", required_argument, NULL, 'T'},
181 {"version", no_argument, NULL, 'V'},
182 {0, 0, 0, 0}
183 };
184
185
186
187
188
189
190 while ((c = getopt_set_loc(argc, argv, "-hT:V", long_options)) != -1) {
191 switch (c) {
192 case '?':
193 exit(EXIT_FAILURE);
194 case 'h':
195 help();
196 exit(EXIT_SUCCESS);
197 case 'T':
198 trace_opt_parse(optarg);
199 trace_init_file();
200 break;
201 case 'V':
202 printf("qemu-storage-daemon version "
203 QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
204 exit(EXIT_SUCCESS);
205 case OPTION_BLOCKDEV:
206 {
207 Visitor *v;
208 BlockdevOptions *options;
209
210 v = qobject_input_visitor_new_str(optarg, "driver",
211 &error_fatal);
212
213 visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
214 visit_free(v);
215
216 qmp_blockdev_add(options, &error_fatal);
217 qapi_free_BlockdevOptions(options);
218 break;
219 }
220 case OPTION_CHARDEV:
221 {
222
223 QemuOpts *opts = qemu_opts_parse_noisily(&qemu_chardev_opts,
224 optarg, true);
225 if (opts == NULL) {
226 exit(EXIT_FAILURE);
227 }
228
229 if (!qemu_chr_new_from_opts(opts, NULL, &error_fatal)) {
230
231 exit(EXIT_SUCCESS);
232 }
233 qemu_opts_del(opts);
234 break;
235 }
236 case OPTION_EXPORT:
237 {
238 Visitor *v;
239 BlockExportOptions *export;
240
241 v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
242 visit_type_BlockExportOptions(v, NULL, &export, &error_fatal);
243 visit_free(v);
244
245 qmp_block_export_add(export, &error_fatal);
246 qapi_free_BlockExportOptions(export);
247 break;
248 }
249 case OPTION_MONITOR:
250 {
251 Visitor *v;
252 MonitorOptions *monitor;
253
254 v = qobject_input_visitor_new_str(optarg, "chardev",
255 &error_fatal);
256 visit_type_MonitorOptions(v, NULL, &monitor, &error_fatal);
257 visit_free(v);
258
259
260 monitor_init(monitor, false, &error_fatal);
261 qapi_free_MonitorOptions(monitor);
262 break;
263 }
264 case OPTION_NBD_SERVER:
265 {
266 Visitor *v;
267 NbdServerOptions *options;
268
269 v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal);
270 visit_type_NbdServerOptions(v, NULL, &options, &error_fatal);
271 visit_free(v);
272
273 nbd_server_start_options(options, &error_fatal);
274 qapi_free_NbdServerOptions(options);
275 break;
276 }
277 case OPTION_OBJECT:
278 user_creatable_process_cmdline(optarg);
279 break;
280 case OPTION_PIDFILE:
281 pid_file = optarg;
282 break;
283 case 1:
284 error_report("Unexpected argument");
285 exit(EXIT_FAILURE);
286 default:
287 g_assert_not_reached();
288 }
289 }
290 loc_set_none();
291}
292
293static void pid_file_cleanup(void)
294{
295 unlink(pid_file);
296}
297
298static void pid_file_init(void)
299{
300 Error *err = NULL;
301
302 if (!pid_file) {
303 return;
304 }
305
306 if (!qemu_write_pidfile(pid_file, &err)) {
307 error_reportf_err(err, "cannot create PID file: ");
308 exit(EXIT_FAILURE);
309 }
310
311 atexit(pid_file_cleanup);
312}
313
314int main(int argc, char *argv[])
315{
316#ifdef CONFIG_POSIX
317 signal(SIGPIPE, SIG_IGN);
318#endif
319
320 error_init(argv[0]);
321 qemu_init_exec_dir(argv[0]);
322 os_setup_signal_handling();
323
324 module_call_init(MODULE_INIT_QOM);
325 module_call_init(MODULE_INIT_TRACE);
326 qemu_add_opts(&qemu_trace_opts);
327 qcrypto_init(&error_fatal);
328 bdrv_init();
329 monitor_init_globals_core();
330 init_qmp_commands();
331
332 if (!trace_init_backends()) {
333 return EXIT_FAILURE;
334 }
335 qemu_set_log(LOG_TRACE);
336
337 qemu_init_main_loop(&error_fatal);
338 process_options(argc, argv);
339
340
341
342
343
344
345 pid_file_init();
346
347 while (!exit_requested) {
348 main_loop_wait(false);
349 }
350
351 blk_exp_close_all();
352 bdrv_drain_all_begin();
353 job_cancel_sync_all();
354 bdrv_close_all();
355
356 monitor_cleanup();
357 qemu_chr_cleanup();
358 user_creatable_cleanup();
359
360 return EXIT_SUCCESS;
361}
362