]> Git Repo - qemu.git/blob - qemu-storage-daemon.c
qemu-storage-daemon: Add main loop
[qemu.git] / qemu-storage-daemon.c
1 /*
2  * QEMU storage daemon
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  * Copyright (c) 2019 Kevin Wolf <[email protected]>
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 "crypto/init.h"
33
34 #include "qapi/error.h"
35 #include "qapi/qapi-commands-block.h"
36 #include "qapi/qapi-commands-block-core.h"
37 #include "qapi/qapi-visit-block.h"
38 #include "qapi/qapi-visit-block-core.h"
39 #include "qapi/qmp/qdict.h"
40 #include "qapi/qobject-input-visitor.h"
41
42 #include "qemu-common.h"
43 #include "qemu-version.h"
44 #include "qemu/config-file.h"
45 #include "qemu/error-report.h"
46 #include "qemu/help_option.h"
47 #include "qemu/log.h"
48 #include "qemu/main-loop.h"
49 #include "qemu/module.h"
50 #include "qemu/option.h"
51 #include "qom/object_interfaces.h"
52
53 #include "sysemu/runstate.h"
54 #include "trace/control.h"
55
56 static volatile bool exit_requested = false;
57
58 void qemu_system_killed(int signal, pid_t pid)
59 {
60     exit_requested = true;
61 }
62
63 static 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"
74 "  --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"
81 "  --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"
86 "  --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"
92 "  --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"
101 QEMU_HELP_BOTTOM "\n",
102     error_get_progname());
103 }
104
105 enum {
106     OPTION_BLOCKDEV = 256,
107     OPTION_EXPORT,
108     OPTION_NBD_SERVER,
109     OPTION_OBJECT,
110 };
111
112 static 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     },
119 };
120
121 static 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
132 static void process_options(int argc, char *argv[])
133 {
134     int c;
135
136     static const struct option long_options[] = {
137         {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
138         {"export", required_argument, NULL, OPTION_EXPORT},
139         {"help", no_argument, NULL, 'h'},
140         {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
141         {"object", required_argument, NULL, OPTION_OBJECT},
142         {"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);
170         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             }
185         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             }
198         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             }
211         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             }
234         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
244 int 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]);
252     os_setup_signal_handling();
253
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
268     while (!exit_requested) {
269         main_loop_wait(false);
270     }
271
272     return EXIT_SUCCESS;
273 }
This page took 0.038218 seconds and 4 git commands to generate.