qemu-storage-daemon.c (11503B)
1/* 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 "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 /* CONFIG_FUSE */ 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, QCO_ALLOW_PRECONFIG); 150} 151 152static int getopt_set_loc(int argc, char **argv, const char *optstring, 153 const struct option *longopts) 154{ 155 int c, save_index; 156 157 optarg = NULL; 158 save_index = optind; 159 c = getopt_long(argc, argv, optstring, longopts, NULL); 160 if (optarg) { 161 loc_set_cmdline(argv, save_index, MAX(1, optind - save_index)); 162 } 163 return c; 164} 165 166static void process_options(int argc, char *argv[]) 167{ 168 int c; 169 170 static const struct option long_options[] = { 171 {"blockdev", required_argument, NULL, OPTION_BLOCKDEV}, 172 {"chardev", required_argument, NULL, OPTION_CHARDEV}, 173 {"export", required_argument, NULL, OPTION_EXPORT}, 174 {"help", no_argument, NULL, 'h'}, 175 {"monitor", required_argument, NULL, OPTION_MONITOR}, 176 {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER}, 177 {"object", required_argument, NULL, OPTION_OBJECT}, 178 {"pidfile", required_argument, NULL, OPTION_PIDFILE}, 179 {"trace", required_argument, NULL, 'T'}, 180 {"version", no_argument, NULL, 'V'}, 181 {0, 0, 0, 0} 182 }; 183 184 /* 185 * In contrast to the system emulator, options are processed in the order 186 * they are given on the command lines. This means that things must be 187 * defined first before they can be referenced in another option. 188 */ 189 while ((c = getopt_set_loc(argc, argv, "-hT:V", long_options)) != -1) { 190 switch (c) { 191 case '?': 192 exit(EXIT_FAILURE); 193 case 'h': 194 help(); 195 exit(EXIT_SUCCESS); 196 case 'T': 197 trace_opt_parse(optarg); 198 trace_init_file(); 199 break; 200 case 'V': 201 printf("qemu-storage-daemon version " 202 QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n"); 203 exit(EXIT_SUCCESS); 204 case OPTION_BLOCKDEV: 205 { 206 Visitor *v; 207 BlockdevOptions *options; 208 209 v = qobject_input_visitor_new_str(optarg, "driver", 210 &error_fatal); 211 212 visit_type_BlockdevOptions(v, NULL, &options, &error_fatal); 213 visit_free(v); 214 215 qmp_blockdev_add(options, &error_fatal); 216 qapi_free_BlockdevOptions(options); 217 break; 218 } 219 case OPTION_CHARDEV: 220 { 221 /* TODO This interface is not stable until we QAPIfy it */ 222 QemuOpts *opts = qemu_opts_parse_noisily(&qemu_chardev_opts, 223 optarg, true); 224 if (opts == NULL) { 225 exit(EXIT_FAILURE); 226 } 227 228 if (!qemu_chr_new_from_opts(opts, NULL, &error_fatal)) { 229 /* No error, but NULL returned means help was printed */ 230 exit(EXIT_SUCCESS); 231 } 232 qemu_opts_del(opts); 233 break; 234 } 235 case OPTION_EXPORT: 236 { 237 Visitor *v; 238 BlockExportOptions *export; 239 240 v = qobject_input_visitor_new_str(optarg, "type", &error_fatal); 241 visit_type_BlockExportOptions(v, NULL, &export, &error_fatal); 242 visit_free(v); 243 244 qmp_block_export_add(export, &error_fatal); 245 qapi_free_BlockExportOptions(export); 246 break; 247 } 248 case OPTION_MONITOR: 249 { 250 Visitor *v; 251 MonitorOptions *monitor; 252 253 v = qobject_input_visitor_new_str(optarg, "chardev", 254 &error_fatal); 255 visit_type_MonitorOptions(v, NULL, &monitor, &error_fatal); 256 visit_free(v); 257 258 /* TODO Catch duplicate monitor IDs */ 259 monitor_init(monitor, false, &error_fatal); 260 qapi_free_MonitorOptions(monitor); 261 break; 262 } 263 case OPTION_NBD_SERVER: 264 { 265 Visitor *v; 266 NbdServerOptions *options; 267 268 v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal); 269 visit_type_NbdServerOptions(v, NULL, &options, &error_fatal); 270 visit_free(v); 271 272 nbd_server_start_options(options, &error_fatal); 273 qapi_free_NbdServerOptions(options); 274 break; 275 } 276 case OPTION_OBJECT: 277 user_creatable_process_cmdline(optarg); 278 break; 279 case OPTION_PIDFILE: 280 pid_file = optarg; 281 break; 282 case 1: 283 error_report("Unexpected argument"); 284 exit(EXIT_FAILURE); 285 default: 286 g_assert_not_reached(); 287 } 288 } 289 loc_set_none(); 290} 291 292static void pid_file_cleanup(void) 293{ 294 unlink(pid_file); 295} 296 297static void pid_file_init(void) 298{ 299 Error *err = NULL; 300 301 if (!pid_file) { 302 return; 303 } 304 305 if (!qemu_write_pidfile(pid_file, &err)) { 306 error_reportf_err(err, "cannot create PID file: "); 307 exit(EXIT_FAILURE); 308 } 309 310 atexit(pid_file_cleanup); 311} 312 313int main(int argc, char *argv[]) 314{ 315#ifdef CONFIG_POSIX 316 signal(SIGPIPE, SIG_IGN); 317#endif 318 319 error_init(argv[0]); 320 qemu_init_exec_dir(argv[0]); 321 os_setup_signal_handling(); 322 323 module_call_init(MODULE_INIT_QOM); 324 module_call_init(MODULE_INIT_TRACE); 325 qemu_add_opts(&qemu_trace_opts); 326 qcrypto_init(&error_fatal); 327 bdrv_init(); 328 monitor_init_globals_core(); 329 init_qmp_commands(); 330 331 if (!trace_init_backends()) { 332 return EXIT_FAILURE; 333 } 334 qemu_set_log(LOG_TRACE); 335 336 qemu_init_main_loop(&error_fatal); 337 process_options(argc, argv); 338 339 /* 340 * Write the pid file after creating chardevs, exports, and NBD servers but 341 * before accepting connections. This ordering is documented. Do not change 342 * it. 343 */ 344 pid_file_init(); 345 346 while (!exit_requested) { 347 main_loop_wait(false); 348 } 349 350 blk_exp_close_all(); 351 bdrv_drain_all_begin(); 352 job_cancel_sync_all(); 353 bdrv_close_all(); 354 355 monitor_cleanup(); 356 qemu_chr_cleanup(); 357 user_creatable_cleanup(); 358 359 return EXIT_SUCCESS; 360}