qemu-nbd.c 28.4 KB
Newer Older
1
/*
B
bellard 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15
 *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
 *
 *  Network Block Device
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; under version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
17 18
 */

P
Peter Maydell 已提交
19
#include "qemu/osdep.h"
20
#include "qemu-common.h"
M
Markus Armbruster 已提交
21
#include "sysemu/block-backend.h"
22
#include "block/block_int.h"
23
#include "block/nbd.h"
24
#include "qemu/main-loop.h"
25
#include "qemu/error-report.h"
26
#include "qemu/config-file.h"
27
#include "block/snapshot.h"
28
#include "qapi/util.h"
29
#include "qapi/qmp/qstring.h"
30
#include "qom/object_interfaces.h"
31
#include "io/channel-socket.h"
B
bellard 已提交
32 33

#include <getopt.h>
34
#include <libgen.h>
P
Paolo Bonzini 已提交
35
#include <pthread.h>
36

37
#define SOCKET_PATH                "/var/lock/qemu-nbd-%s"
38 39 40 41 42 43 44
#define QEMU_NBD_OPT_CACHE         256
#define QEMU_NBD_OPT_AIO           257
#define QEMU_NBD_OPT_DISCARD       258
#define QEMU_NBD_OPT_DETECT_ZEROES 259
#define QEMU_NBD_OPT_OBJECT        260
#define QEMU_NBD_OPT_TLSCREDS      261
#define QEMU_NBD_OPT_IMAGE_OPTS    262
B
bellard 已提交
45

P
Paolo Bonzini 已提交
46
static NBDExport *exp;
47
static bool newproto;
48
static int verbose;
P
Paolo Bonzini 已提交
49
static char *srcpath;
50
static SocketAddress *saddr;
51 52
static int persistent = 0;
static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state;
P
Paolo Bonzini 已提交
53 54
static int shared = 1;
static int nb_fds;
55 56
static QIOChannelSocket *server_ioc;
static int server_watch = -1;
57
static QCryptoTLSCreds *tlscreds;
B
bellard 已提交
58 59 60

static void usage(const char *name)
{
61
    (printf) (
B
bellard 已提交
62 63 64
"Usage: %s [OPTIONS] FILE\n"
"QEMU Disk Network Block Device Server\n"
"\n"
65 66
"  -h, --help                display this help and exit\n"
"  -V, --version             output version information and exit\n"
67 68
"\n"
"Connection properties:\n"
69 70 71 72 73 74 75
"  -p, --port=PORT           port to listen on (default `%d')\n"
"  -b, --bind=IFACE          interface to bind to (default `0.0.0.0')\n"
"  -k, --socket=PATH         path to the unix socket\n"
"                            (default '"SOCKET_PATH"')\n"
"  -e, --shared=NUM          device can be shared by NUM clients (default '1')\n"
"  -t, --persistent          don't exit on the last connection\n"
"  -v, --verbose             display extra debugging information\n"
B
bellard 已提交
76
"\n"
77
"Exposing part of the image:\n"
78 79
"  -o, --offset=OFFSET       offset into the image\n"
"  -P, --partition=NUM       only expose partition NUM\n"
80
"\n"
81 82 83
"General purpose options:\n"
"  --object type,id=ID,...   define an object such as 'secret' for providing\n"
"                            passwords and/or encryption keys\n"
84 85
#ifdef __linux__
"Kernel NBD client support:\n"
86 87
"  -c, --connect=DEV         connect FILE to the local NBD device DEV\n"
"  -d, --disconnect          disconnect the specified device\n"
88 89 90 91
"\n"
#endif
"\n"
"Block device options:\n"
92 93 94 95 96
"  -f, --format=FORMAT       set image format (raw, qcow2, ...)\n"
"  -r, --read-only           export read-only\n"
"  -s, --snapshot            use FILE as an external snapshot, create a temporary\n"
"                            file with backing_file=FILE, redirect the write to\n"
"                            the temporary one\n"
97
"  -l, --load-snapshot=SNAPSHOT_PARAM\n"
98 99 100 101 102 103 104
"                            load an internal snapshot inside FILE and export it\n"
"                            as an read-only device, SNAPSHOT_PARAM format is\n"
"                            'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
"                            '[ID_OR_NAME]'\n"
"  -n, --nocache             disable host cache\n"
"      --cache=MODE          set cache mode (none, writeback, ...)\n"
"      --aio=MODE            set AIO mode (native or threads)\n"
105
"      --discard=MODE        set discard mode (ignore, unmap)\n"
106
"      --detect-zeroes=MODE  set detect-zeroes mode (off, on, unmap)\n"
107
"      --image-opts          treat FILE as a full set of image options\n"
108 109
"\n"
"Report bugs to <qemu-devel@nongnu.org>\n"
110
    , name, NBD_DEFAULT_PORT, "DEVICE");
B
bellard 已提交
111 112 113 114 115
}

static void version(const char *name)
{
    printf(
116
"%s version 0.0.1\n"
B
bellard 已提交
117 118 119 120 121
"Written by Anthony Liguori.\n"
"\n"
"Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>.\n"
"This is free software; see the source for copying conditions.  There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
122
    , name);
B
bellard 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
}

struct partition_record
{
    uint8_t bootable;
    uint8_t start_head;
    uint32_t start_cylinder;
    uint8_t start_sector;
    uint8_t system;
    uint8_t end_head;
    uint8_t end_cylinder;
    uint8_t end_sector;
    uint32_t start_sector_abs;
    uint32_t nb_sectors_abs;
};

static void read_partition(uint8_t *p, struct partition_record *r)
{
    r->bootable = p[0];
    r->start_head = p[1];
    r->start_cylinder = p[3] | ((p[2] << 2) & 0x0300);
    r->start_sector = p[2] & 0x3f;
    r->system = p[4];
    r->end_head = p[5];
    r->end_cylinder = p[7] | ((p[6] << 2) & 0x300);
    r->end_sector = p[6] & 0x3f;
149 150 151

    r->start_sector_abs = le32_to_cpup((uint32_t *)(p +  8));
    r->nb_sectors_abs   = le32_to_cpup((uint32_t *)(p + 12));
B
bellard 已提交
152 153
}

154
static int find_partition(BlockBackend *blk, int partition,
B
bellard 已提交
155 156 157 158 159 160
                          off_t *offset, off_t *size)
{
    struct partition_record mbr[4];
    uint8_t data[512];
    int i;
    int ext_partnum = 4;
R
Ryota Ozaki 已提交
161
    int ret;
B
bellard 已提交
162

163
    if ((ret = blk_read(blk, 0, data, 1)) < 0) {
164
        error_report("error while reading: %s", strerror(-ret));
165
        exit(EXIT_FAILURE);
R
Ryota Ozaki 已提交
166
    }
B
bellard 已提交
167 168

    if (data[510] != 0x55 || data[511] != 0xaa) {
169
        return -EINVAL;
B
bellard 已提交
170 171 172 173 174
    }

    for (i = 0; i < 4; i++) {
        read_partition(&data[446 + 16 * i], &mbr[i]);

175
        if (!mbr[i].system || !mbr[i].nb_sectors_abs) {
B
bellard 已提交
176
            continue;
177
        }
B
bellard 已提交
178 179 180 181 182 183

        if (mbr[i].system == 0xF || mbr[i].system == 0x5) {
            struct partition_record ext[4];
            uint8_t data1[512];
            int j;

184
            if ((ret = blk_read(blk, mbr[i].start_sector_abs, data1, 1)) < 0) {
185
                error_report("error while reading: %s", strerror(-ret));
186
                exit(EXIT_FAILURE);
R
Ryota Ozaki 已提交
187
            }
B
bellard 已提交
188 189 190

            for (j = 0; j < 4; j++) {
                read_partition(&data1[446 + 16 * j], &ext[j]);
191
                if (!ext[j].system || !ext[j].nb_sectors_abs) {
B
bellard 已提交
192
                    continue;
193
                }
B
bellard 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

                if ((ext_partnum + j + 1) == partition) {
                    *offset = (uint64_t)ext[j].start_sector_abs << 9;
                    *size = (uint64_t)ext[j].nb_sectors_abs << 9;
                    return 0;
                }
            }
            ext_partnum += 4;
        } else if ((i + 1) == partition) {
            *offset = (uint64_t)mbr[i].start_sector_abs << 9;
            *size = (uint64_t)mbr[i].nb_sectors_abs << 9;
            return 0;
        }
    }

209
    return -ENOENT;
B
bellard 已提交
210 211
}

P
Paolo Bonzini 已提交
212 213
static void termsig_handler(int signum)
{
214
    state = TERMINATE;
P
Paolo Bonzini 已提交
215
    qemu_notify_event();
P
Paolo Bonzini 已提交
216 217
}

218

P
Paolo Bonzini 已提交
219
static void *show_parts(void *arg)
220
{
221
    char *device = arg;
P
Paolo Bonzini 已提交
222 223 224 225 226 227 228 229
    int nbd;

    /* linux just needs an open() to trigger
     * the partition table update
     * but remember to load the module with max_part != 0 :
     *     modprobe nbd max_part=63
     */
    nbd = open(device, O_RDWR);
230
    if (nbd >= 0) {
P
Paolo Bonzini 已提交
231 232 233 234
        close(nbd);
    }
    return NULL;
}
235

P
Paolo Bonzini 已提交
236 237
static void *nbd_client_thread(void *arg)
{
238
    char *device = arg;
P
Paolo Bonzini 已提交
239 240
    off_t size;
    uint32_t nbdflags;
241 242
    QIOChannelSocket *sioc;
    int fd;
P
Paolo Bonzini 已提交
243 244
    int ret;
    pthread_t show_parts_thread;
M
Max Reitz 已提交
245
    Error *local_error = NULL;
P
Paolo Bonzini 已提交
246

247 248 249 250
    sioc = qio_channel_socket_new();
    if (qio_channel_socket_connect_sync(sioc,
                                        saddr,
                                        &local_error) < 0) {
251
        error_report_err(local_error);
252 253
        goto out;
    }
P
Paolo Bonzini 已提交
254

255
    ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL, &nbdflags,
256
                                NULL, NULL, NULL,
257
                                &size, &local_error);
258
    if (ret < 0) {
M
Max Reitz 已提交
259
        if (local_error) {
260
            error_report_err(local_error);
M
Max Reitz 已提交
261
        }
P
Paolo Bonzini 已提交
262
        goto out_socket;
P
Paolo Bonzini 已提交
263 264
    }

265
    fd = open(device, O_RDWR);
266
    if (fd < 0) {
267
        /* Linux-only, we can use %m in printf.  */
268
        error_report("Failed to open %s: %m", device);
P
Paolo Bonzini 已提交
269
        goto out_socket;
270 271
    }

272
    ret = nbd_init(fd, sioc, nbdflags, size);
273
    if (ret < 0) {
P
Paolo Bonzini 已提交
274
        goto out_fd;
P
Paolo Bonzini 已提交
275 276 277
    }

    /* update partition table */
278
    pthread_create(&show_parts_thread, NULL, show_parts, device);
P
Paolo Bonzini 已提交
279

280 281 282 283 284 285 286
    if (verbose) {
        fprintf(stderr, "NBD device %s is now connected to %s\n",
                device, srcpath);
    } else {
        /* Close stderr so that the qemu-nbd process exits.  */
        dup2(STDOUT_FILENO, STDERR_FILENO);
    }
P
Paolo Bonzini 已提交
287 288 289

    ret = nbd_client(fd);
    if (ret) {
P
Paolo Bonzini 已提交
290
        goto out_fd;
291
    }
P
Paolo Bonzini 已提交
292
    close(fd);
293
    object_unref(OBJECT(sioc));
P
Paolo Bonzini 已提交
294 295 296
    kill(getpid(), SIGTERM);
    return (void *) EXIT_SUCCESS;

P
Paolo Bonzini 已提交
297 298 299
out_fd:
    close(fd);
out_socket:
300
    object_unref(OBJECT(sioc));
P
Paolo Bonzini 已提交
301 302 303
out:
    kill(getpid(), SIGTERM);
    return (void *) EXIT_FAILURE;
304 305
}

306
static int nbd_can_accept(void)
P
Paolo Bonzini 已提交
307 308 309 310
{
    return nb_fds < shared;
}

311 312 313 314 315 316
static void nbd_export_closed(NBDExport *exp)
{
    assert(state == TERMINATING);
    state = TERMINATED;
}

317
static void nbd_update_server_watch(void);
318

319
static void nbd_client_closed(NBDClient *client)
P
Paolo Bonzini 已提交
320
{
321
    nb_fds--;
322 323 324
    if (nb_fds == 0 && !persistent && state == RUNNING) {
        state = TERMINATE;
    }
325
    nbd_update_server_watch();
326
    nbd_client_put(client);
P
Paolo Bonzini 已提交
327 328
}

329
static gboolean nbd_accept(QIOChannel *ioc, GIOCondition cond, gpointer opaque)
P
Paolo Bonzini 已提交
330
{
331
    QIOChannelSocket *cioc;
P
Paolo Bonzini 已提交
332

333 334 335 336
    cioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc),
                                     NULL);
    if (!cioc) {
        return TRUE;
P
Paolo Bonzini 已提交
337 338
    }

339
    if (state >= TERMINATE) {
340 341
        object_unref(OBJECT(cioc));
        return TRUE;
342 343
    }

344
    nb_fds++;
345
    nbd_update_server_watch();
346
    nbd_client_new(newproto ? NULL : exp, cioc,
347
                   tlscreds, NULL, nbd_client_closed);
348 349 350
    object_unref(OBJECT(cioc));

    return TRUE;
P
Paolo Bonzini 已提交
351 352
}

353
static void nbd_update_server_watch(void)
354 355
{
    if (nbd_can_accept()) {
356 357 358 359 360 361
        if (server_watch == -1) {
            server_watch = qio_channel_add_watch(QIO_CHANNEL(server_ioc),
                                                 G_IO_IN,
                                                 nbd_accept,
                                                 NULL, NULL);
        }
362
    } else {
363 364 365 366
        if (server_watch != -1) {
            g_source_remove(server_watch);
            server_watch = -1;
        }
367 368 369
    }
}

370 371 372 373 374 375 376 377 378

static SocketAddress *nbd_build_socket_address(const char *sockpath,
                                               const char *bindto,
                                               const char *port)
{
    SocketAddress *saddr;

    saddr = g_new0(SocketAddress, 1);
    if (sockpath) {
379
        saddr->type = SOCKET_ADDRESS_KIND_UNIX;
380 381
        saddr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
        saddr->u.q_unix.data->path = g_strdup(sockpath);
382
    } else {
383
        InetSocketAddress *inet;
384
        saddr->type = SOCKET_ADDRESS_KIND_INET;
385
        inet = saddr->u.inet.data = g_new0(InetSocketAddress, 1);
386
        inet->host = g_strdup(bindto);
387
        if (port) {
388
            inet->port = g_strdup(port);
389
        } else  {
390
            inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
391 392 393 394 395 396 397
        }
    }

    return saddr;
}


398 399 400 401 402 403 404 405 406 407
static QemuOptsList file_opts = {
    .name = "file",
    .implied_opt_name = "file",
    .head = QTAILQ_HEAD_INITIALIZER(file_opts.head),
    .desc = {
        /* no elements => accept any params */
        { /* end of list */ }
    },
};

408 409 410 411 412 413 414 415 416 417
static QemuOptsList qemu_object_opts = {
    .name = "object",
    .implied_opt_name = "qom-type",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
    .desc = {
        { }
    },
};


418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448

static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
{
    Object *obj;
    QCryptoTLSCreds *creds;

    obj = object_resolve_path_component(
        object_get_objects_root(), id);
    if (!obj) {
        error_setg(errp, "No TLS credentials with id '%s'",
                   id);
        return NULL;
    }
    creds = (QCryptoTLSCreds *)
        object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS);
    if (!creds) {
        error_setg(errp, "Object with id '%s' is not TLS credentials",
                   id);
        return NULL;
    }

    if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
        error_setg(errp,
                   "Expecting TLS credentials with a server endpoint");
        return NULL;
    }
    object_ref(obj);
    return creds;
}


B
bellard 已提交
449 450
int main(int argc, char **argv)
{
M
Markus Armbruster 已提交
451
    BlockBackend *blk;
B
bellard 已提交
452 453
    BlockDriverState *bs;
    off_t dev_offset = 0;
P
Paolo Bonzini 已提交
454
    uint32_t nbdflags = 0;
455
    bool disconnect = false;
B
bellard 已提交
456
    const char *bindto = "0.0.0.0";
457 458
    const char *port = NULL;
    char *sockpath = NULL;
459
    char *device = NULL;
B
bellard 已提交
460
    off_t fd_size;
461 462
    QemuOpts *sn_opts = NULL;
    const char *sn_id_or_name = NULL;
463
    const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:x:";
B
bellard 已提交
464
    struct option lopt[] = {
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
        { "help", no_argument, NULL, 'h' },
        { "version", no_argument, NULL, 'V' },
        { "bind", required_argument, NULL, 'b' },
        { "port", required_argument, NULL, 'p' },
        { "socket", required_argument, NULL, 'k' },
        { "offset", required_argument, NULL, 'o' },
        { "read-only", no_argument, NULL, 'r' },
        { "partition", required_argument, NULL, 'P' },
        { "connect", required_argument, NULL, 'c' },
        { "disconnect", no_argument, NULL, 'd' },
        { "snapshot", no_argument, NULL, 's' },
        { "load-snapshot", required_argument, NULL, 'l' },
        { "nocache", no_argument, NULL, 'n' },
        { "cache", required_argument, NULL, QEMU_NBD_OPT_CACHE },
        { "aio", required_argument, NULL, QEMU_NBD_OPT_AIO },
        { "discard", required_argument, NULL, QEMU_NBD_OPT_DISCARD },
        { "detect-zeroes", required_argument, NULL,
          QEMU_NBD_OPT_DETECT_ZEROES },
        { "shared", required_argument, NULL, 'e' },
        { "format", required_argument, NULL, 'f' },
        { "persistent", no_argument, NULL, 't' },
        { "verbose", no_argument, NULL, 'v' },
        { "object", required_argument, NULL, QEMU_NBD_OPT_OBJECT },
        { "export-name", required_argument, NULL, 'x' },
        { "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS },
        { "image-opts", no_argument, NULL, QEMU_NBD_OPT_IMAGE_OPTS },
491
        { NULL, 0, NULL, 0 }
B
bellard 已提交
492 493 494 495
    };
    int ch;
    int opt_ind = 0;
    char *end;
496
    int flags = BDRV_O_RDWR;
B
bellard 已提交
497
    int partition = -1;
498
    int ret = 0;
499
    bool seen_cache = false;
P
Paolo Bonzini 已提交
500
    bool seen_discard = false;
501
    bool seen_aio = false;
P
Paolo Bonzini 已提交
502
    pthread_t client_thread;
503
    const char *fmt = NULL;
504
    Error *local_err = NULL;
505
    BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;
506
    QDict *options = NULL;
507
    const char *export_name = NULL;
508
    const char *tlscredsid = NULL;
509
    bool imageOpts = false;
B
bellard 已提交
510

P
Paolo Bonzini 已提交
511 512 513
    /* The client thread uses SIGTERM to interrupt the server.  A signal
     * handler ensures that "qemu-nbd -v -c" exits with a nice status code.
     */
P
Paolo Bonzini 已提交
514 515 516 517
    struct sigaction sa_sigterm;
    memset(&sa_sigterm, 0, sizeof(sa_sigterm));
    sa_sigterm.sa_handler = termsig_handler;
    sigaction(SIGTERM, &sa_sigterm, NULL);
518 519
    module_call_init(MODULE_INIT_QOM);
    qemu_add_opts(&qemu_object_opts);
520
    qemu_init_exec_dir(argv[0]);
P
Paolo Bonzini 已提交
521

B
bellard 已提交
522 523 524
    while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
        switch (ch) {
        case 's':
525 526 527
            flags |= BDRV_O_SNAPSHOT;
            break;
        case 'n':
528 529 530 531
            optarg = (char *) "none";
            /* fallthrough */
        case QEMU_NBD_OPT_CACHE:
            if (seen_cache) {
532 533
                error_report("-n and --cache can only be specified once");
                exit(EXIT_FAILURE);
534 535 536
            }
            seen_cache = true;
            if (bdrv_parse_cache_flags(optarg, &flags) == -1) {
537 538
                error_report("Invalid cache mode `%s'", optarg);
                exit(EXIT_FAILURE);
539
            }
B
bellard 已提交
540
            break;
541 542
        case QEMU_NBD_OPT_AIO:
            if (seen_aio) {
543 544
                error_report("--aio can only be specified once");
                exit(EXIT_FAILURE);
545 546 547 548 549 550 551
            }
            seen_aio = true;
            if (!strcmp(optarg, "native")) {
                flags |= BDRV_O_NATIVE_AIO;
            } else if (!strcmp(optarg, "threads")) {
                /* this is the default */
            } else {
552 553
               error_report("invalid aio mode `%s'", optarg);
               exit(EXIT_FAILURE);
554 555
            }
            break;
P
Paolo Bonzini 已提交
556 557
        case QEMU_NBD_OPT_DISCARD:
            if (seen_discard) {
558 559
                error_report("--discard can only be specified once");
                exit(EXIT_FAILURE);
P
Paolo Bonzini 已提交
560 561 562
            }
            seen_discard = true;
            if (bdrv_parse_discard_flags(optarg, &flags) == -1) {
563 564
                error_report("Invalid discard mode `%s'", optarg);
                exit(EXIT_FAILURE);
P
Paolo Bonzini 已提交
565 566
            }
            break;
567 568 569 570
        case QEMU_NBD_OPT_DETECT_ZEROES:
            detect_zeroes =
                qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
                                optarg,
571
                                BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
572 573 574
                                BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
                                &local_err);
            if (local_err) {
575 576
                error_reportf_err(local_err,
                                  "Failed to parse detect_zeroes mode: ");
577
                exit(EXIT_FAILURE);
578 579 580
            }
            if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
                !(flags & BDRV_O_UNMAP)) {
581 582 583
                error_report("setting detect-zeroes to unmap is not allowed "
                             "without setting discard operation to unmap");
                exit(EXIT_FAILURE);
584 585
            }
            break;
B
bellard 已提交
586 587 588 589
        case 'b':
            bindto = optarg;
            break;
        case 'p':
590
            port = optarg;
B
bellard 已提交
591 592 593 594
            break;
        case 'o':
                dev_offset = strtoll (optarg, &end, 0);
            if (*end) {
595 596
                error_report("Invalid offset `%s'", optarg);
                exit(EXIT_FAILURE);
B
bellard 已提交
597 598
            }
            if (dev_offset < 0) {
599 600
                error_report("Offset must be positive `%s'", optarg);
                exit(EXIT_FAILURE);
B
bellard 已提交
601 602
            }
            break;
603 604
        case 'l':
            if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
605 606
                sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
                                                  optarg, false);
607
                if (!sn_opts) {
608 609 610
                    error_report("Failed in parsing snapshot param `%s'",
                                 optarg);
                    exit(EXIT_FAILURE);
611 612 613 614 615
                }
            } else {
                sn_id_or_name = optarg;
            }
            /* fall through */
B
bellard 已提交
616
        case 'r':
P
Paolo Bonzini 已提交
617
            nbdflags |= NBD_FLAG_READ_ONLY;
N
Naphtali Sprei 已提交
618
            flags &= ~BDRV_O_RDWR;
B
bellard 已提交
619 620 621
            break;
        case 'P':
            partition = strtol(optarg, &end, 0);
622
            if (*end) {
623 624
                error_report("Invalid partition `%s'", optarg);
                exit(EXIT_FAILURE);
625 626
            }
            if (partition < 1 || partition > 8) {
627 628
                error_report("Invalid partition %d", partition);
                exit(EXIT_FAILURE);
629
            }
B
bellard 已提交
630
            break;
631
        case 'k':
P
Paolo Bonzini 已提交
632
            sockpath = optarg;
633
            if (sockpath[0] != '/') {
634
                error_report("socket path must be absolute");
635
                exit(EXIT_FAILURE);
636
            }
637 638 639 640 641 642 643
            break;
        case 'd':
            disconnect = true;
            break;
        case 'c':
            device = optarg;
            break;
644 645 646
        case 'e':
            shared = strtol(optarg, &end, 0);
            if (*end) {
647 648
                error_report("Invalid shared device number '%s'", optarg);
                exit(EXIT_FAILURE);
649 650
            }
            if (shared < 1) {
651
                error_report("Shared device number must be greater than 0");
652
                exit(EXIT_FAILURE);
653 654
            }
            break;
655 656 657
        case 'f':
            fmt = optarg;
            break;
658 659 660
        case 't':
            persistent = 1;
            break;
661 662 663
        case 'x':
            export_name = optarg;
            break;
B
bellard 已提交
664 665 666 667 668 669 670 671 672 673 674 675
        case 'v':
            verbose = 1;
            break;
        case 'V':
            version(argv[0]);
            exit(0);
            break;
        case 'h':
            usage(argv[0]);
            exit(0);
            break;
        case '?':
676 677
            error_report("Try `%s --help' for more information.", argv[0]);
            exit(EXIT_FAILURE);
678 679 680 681 682 683 684 685
        case QEMU_NBD_OPT_OBJECT: {
            QemuOpts *opts;
            opts = qemu_opts_parse_noisily(&qemu_object_opts,
                                           optarg, true);
            if (!opts) {
                exit(EXIT_FAILURE);
            }
        }   break;
686 687 688
        case QEMU_NBD_OPT_TLSCREDS:
            tlscredsid = optarg;
            break;
689 690 691
        case QEMU_NBD_OPT_IMAGE_OPTS:
            imageOpts = true;
            break;
B
bellard 已提交
692 693 694 695
        }
    }

    if ((argc - optind) != 1) {
696 697
        error_report("Invalid number of arguments");
        error_printf("Try `%s --help' for more information.\n", argv[0]);
698
        exit(EXIT_FAILURE);
B
bellard 已提交
699 700
    }

701 702 703 704 705 706 707
    if (qemu_opts_foreach(&qemu_object_opts,
                          user_creatable_add_opts_foreach,
                          NULL, &local_err)) {
        error_report_err(local_err);
        exit(EXIT_FAILURE);
    }

708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
    if (tlscredsid) {
        if (sockpath) {
            error_report("TLS is only supported with IPv4/IPv6");
            exit(EXIT_FAILURE);
        }
        if (device) {
            error_report("TLS is not supported with a host device");
            exit(EXIT_FAILURE);
        }
        if (!export_name) {
            /* Set the default NBD protocol export name, since
             * we *must* use new style protocol for TLS */
            export_name = "";
        }
        tlscreds = nbd_get_tls_creds(tlscredsid, &local_err);
        if (local_err) {
            error_report("Failed to get TLS creds %s",
                         error_get_pretty(local_err));
            exit(EXIT_FAILURE);
        }
    }

730
    if (disconnect) {
731 732
        int nbdfd = open(argv[optind], O_RDWR);
        if (nbdfd < 0) {
733 734 735
            error_report("Cannot open %s: %s", argv[optind],
                         strerror(errno));
            exit(EXIT_FAILURE);
736
        }
737
        nbd_disconnect(nbdfd);
738

739
        close(nbdfd);
740 741 742

        printf("%s disconnected\n", argv[optind]);

743
        return 0;
744 745
    }

746 747 748 749 750
    if (device && !verbose) {
        int stderr_fd[2];
        pid_t pid;
        int ret;

751
        if (qemu_pipe(stderr_fd) < 0) {
752 753 754
            error_report("Error setting up communication pipe: %s",
                         strerror(errno));
            exit(EXIT_FAILURE);
755 756 757 758 759 760
        }

        /* Now daemonize, but keep a communication channel open to
         * print errors and exit with the proper status code.
         */
        pid = fork();
M
Max Reitz 已提交
761
        if (pid < 0) {
762 763
            error_report("Failed to fork: %s", strerror(errno));
            exit(EXIT_FAILURE);
M
Max Reitz 已提交
764
        } else if (pid == 0) {
765
            close(stderr_fd[0]);
766
            ret = qemu_daemon(1, 0);
767 768 769

            /* Temporarily redirect stderr to the parent's pipe...  */
            dup2(stderr_fd[1], STDERR_FILENO);
770
            if (ret < 0) {
771 772
                error_report("Failed to daemonize: %s", strerror(errno));
                exit(EXIT_FAILURE);
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
            }

            /* ... close the descriptor we inherited and go on.  */
            close(stderr_fd[1]);
        } else {
            bool errors = false;
            char *buf;

            /* In the parent.  Print error messages from the child until
             * it closes the pipe.
             */
            close(stderr_fd[1]);
            buf = g_malloc(1024);
            while ((ret = read(stderr_fd[0], buf, 1024)) > 0) {
                errors = true;
                ret = qemu_write_full(STDERR_FILENO, buf, ret);
789
                if (ret < 0) {
790 791 792
                    exit(EXIT_FAILURE);
                }
            }
793
            if (ret < 0) {
794 795 796
                error_report("Cannot read from daemon: %s",
                             strerror(errno));
                exit(EXIT_FAILURE);
797 798 799 800 801 802 803 804 805
            }

            /* Usually the daemon should not print any message.
             * Exit with zero status in that case.
             */
            exit(errors);
        }
    }

806 807 808
    if (device != NULL && sockpath == NULL) {
        sockpath = g_malloc(128);
        snprintf(sockpath, 128, SOCKET_PATH, basename(device));
809 810
    }

811 812
    saddr = nbd_build_socket_address(sockpath, bindto, port);

813
    if (qemu_init_main_loop(&local_err)) {
814
        error_report_err(local_err);
815 816
        exit(EXIT_FAILURE);
    }
817 818 819
    bdrv_init();
    atexit(bdrv_close_all);

820 821 822 823 824 825 826 827 828 829 830 831 832 833
    srcpath = argv[optind];
    if (imageOpts) {
        QemuOpts *opts;
        if (fmt) {
            error_report("--image-opts and -f are mutually exclusive");
            exit(EXIT_FAILURE);
        }
        opts = qemu_opts_parse_noisily(&file_opts, srcpath, true);
        if (!opts) {
            qemu_opts_reset(&file_opts);
            exit(EXIT_FAILURE);
        }
        options = qemu_opts_to_qdict(opts, NULL);
        qemu_opts_reset(&file_opts);
834
        blk = blk_new_open(NULL, NULL, options, flags, &local_err);
835 836 837 838 839
    } else {
        if (fmt) {
            options = qdict_new();
            qdict_put(options, "driver", qstring_from_str(fmt));
        }
840
        blk = blk_new_open(srcpath, NULL, options, flags, &local_err);
841 842
    }

843
    if (!blk) {
844 845
        error_reportf_err(local_err, "Failed to blk_new_open '%s': ",
                          argv[optind]);
846
        exit(EXIT_FAILURE);
847
    }
848
    bs = blk_bs(blk);
849

850 851 852 853 854 855 856 857 858 859
    if (sn_opts) {
        ret = bdrv_snapshot_load_tmp(bs,
                                     qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
                                     qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
                                     &local_err);
    } else if (sn_id_or_name) {
        ret = bdrv_snapshot_load_tmp_by_id_or_name(bs, sn_id_or_name,
                                                   &local_err);
    }
    if (ret < 0) {
860
        error_reportf_err(local_err, "Failed to load snapshot: ");
861
        exit(EXIT_FAILURE);
862 863
    }

864
    bs->detect_zeroes = detect_zeroes;
865
    fd_size = blk_getlength(blk);
M
Max Reitz 已提交
866
    if (fd_size < 0) {
867 868 869
        error_report("Failed to determine the image length: %s",
                     strerror(-fd_size));
        exit(EXIT_FAILURE);
M
Max Reitz 已提交
870
    }
871

872
    if (partition != -1) {
873
        ret = find_partition(blk, partition, &dev_offset, &fd_size);
874
        if (ret < 0) {
875
            error_report("Could not find partition %d: %s", partition,
876
                         strerror(-ret));
877
            exit(EXIT_FAILURE);
878
        }
879 880
    }

M
Max Reitz 已提交
881 882 883
    exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed,
                         &local_err);
    if (!exp) {
884
        error_report_err(local_err);
885
        exit(EXIT_FAILURE);
M
Max Reitz 已提交
886
    }
887 888 889 890
    if (export_name) {
        nbd_export_set_name(exp, export_name);
        newproto = true;
    }
891

892 893 894
    server_ioc = qio_channel_socket_new();
    if (qio_channel_socket_listen_sync(server_ioc, saddr, &local_err) < 0) {
        object_unref(OBJECT(server_ioc));
895
        error_report_err(local_err);
B
bellard 已提交
896
        return 1;
P
Paolo Bonzini 已提交
897
    }
P
Paolo Bonzini 已提交
898 899 900 901

    if (device) {
        int ret;

902
        ret = pthread_create(&client_thread, NULL, nbd_client_thread, device);
P
Paolo Bonzini 已提交
903
        if (ret != 0) {
904 905
            error_report("Failed to create client thread: %s", strerror(ret));
            exit(EXIT_FAILURE);
P
Paolo Bonzini 已提交
906 907 908 909 910 911
        }
    } else {
        /* Shut up GCC warnings.  */
        memset(&client_thread, 0, sizeof(client_thread));
    }

912
    nbd_update_server_watch();
B
bellard 已提交
913

914 915 916
    /* now when the initialization is (almost) complete, chdir("/")
     * to free any busy filesystems */
    if (chdir("/") < 0) {
917 918 919
        error_report("Could not chdir to root directory: %s",
                     strerror(errno));
        exit(EXIT_FAILURE);
920 921
    }

922
    state = RUNNING;
923
    do {
P
Paolo Bonzini 已提交
924
        main_loop_wait(false);
925 926 927 928 929 930 931
        if (state == TERMINATE) {
            state = TERMINATING;
            nbd_export_close(exp);
            nbd_export_put(exp);
            exp = NULL;
        }
    } while (state != TERMINATED);
B
bellard 已提交
932

M
Markus Armbruster 已提交
933
    blk_unref(blk);
P
Paolo Bonzini 已提交
934 935 936
    if (sockpath) {
        unlink(sockpath);
    }
B
bellard 已提交
937

938
    qemu_opts_del(sn_opts);
939

P
Paolo Bonzini 已提交
940 941 942 943 944 945 946
    if (device) {
        void *ret;
        pthread_join(client_thread, &ret);
        exit(ret != NULL);
    } else {
        exit(EXIT_SUCCESS);
    }
B
bellard 已提交
947
}