qemu/storage-daemon/qemu-storage-daemon.c
<<
>>
Prefs
   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,
 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     * In contrast to the system emulator, options are processed in the order
 187     * they are given on the command lines. This means that things must be
 188     * defined first before they can be referenced in another option.
 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                /* TODO This interface is not stable until we QAPIfy it */
 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                    /* No error, but NULL returned means help was printed */
 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                /* TODO Catch duplicate monitor IDs */
 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     * Write the pid file after creating chardevs, exports, and NBD servers but
 342     * before accepting connections. This ordering is documented. Do not change
 343     * it.
 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