server.c 38.7 KB
Newer Older
1
/*
2
 *  Copyright (C) 2016 Red Hat, Inc.
B
bellard 已提交
3 4
 *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
 *
F
Fam Zheng 已提交
5
 *  Network Block Device Server Side
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16
 *
 *  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
17
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18
 */
B
bellard 已提交
19

P
Peter Maydell 已提交
20
#include "qemu/osdep.h"
21
#include "qapi/error.h"
F
Fam Zheng 已提交
22
#include "nbd-internal.h"
23 24 25 26 27 28 29

static int system_errno_to_nbd_errno(int err)
{
    switch (err) {
    case 0:
        return NBD_SUCCESS;
    case EPERM:
30
    case EROFS:
31 32 33 34 35 36 37 38 39 40 41
        return NBD_EPERM;
    case EIO:
        return NBD_EIO;
    case ENOMEM:
        return NBD_ENOMEM;
#ifdef EDQUOT
    case EDQUOT:
#endif
    case EFBIG:
    case ENOSPC:
        return NBD_ENOSPC;
42 43
    case ESHUTDOWN:
        return NBD_ESHUTDOWN;
44 45 46 47 48 49
    case EINVAL:
    default:
        return NBD_EINVAL;
    }
}

50 51
/* Definitions for opaque data types */

52
typedef struct NBDRequestData NBDRequestData;
53

54 55
struct NBDRequestData {
    QSIMPLEQ_ENTRY(NBDRequestData) entry;
56 57
    NBDClient *client;
    uint8_t *data;
58
    bool complete;
59 60 61
};

struct NBDExport {
62
    int refcount;
63 64
    void (*close)(NBDExport *exp);

M
Max Reitz 已提交
65
    BlockBackend *blk;
P
Paolo Bonzini 已提交
66
    char *name;
67
    char *description;
68 69
    off_t dev_offset;
    off_t size;
E
Eric Blake 已提交
70
    uint16_t nbdflags;
71
    QTAILQ_HEAD(, NBDClient) clients;
P
Paolo Bonzini 已提交
72
    QTAILQ_ENTRY(NBDExport) next;
M
Max Reitz 已提交
73 74

    AioContext *ctx;
75

76
    BlockBackend *eject_notifier_blk;
77
    Notifier eject_notifier;
78 79
};

P
Paolo Bonzini 已提交
80 81
static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);

82 83
struct NBDClient {
    int refcount;
84
    void (*close_fn)(NBDClient *client, bool negotiated);
85

E
Eric Blake 已提交
86
    bool no_zeroes;
87
    NBDExport *exp;
88 89
    QCryptoTLSCreds *tlscreds;
    char *tlsaclname;
90 91
    QIOChannelSocket *sioc; /* The underlying data channel */
    QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
92 93 94 95 96 97

    Coroutine *recv_coroutine;

    CoMutex send_lock;
    Coroutine *send_coroutine;

98
    QTAILQ_ENTRY(NBDClient) next;
99
    int nb_requests;
100
    bool closing;
101 102
};

B
bellard 已提交
103 104
/* That's all folks */

105
static void nbd_client_receive_next_request(NBDClient *client);
M
Max Reitz 已提交
106

107
/* Basic flow for negotiation
B
bellard 已提交
108 109 110

   Server         Client
   Negotiate
111 112 113 114 115 116 117 118 119 120 121 122 123

   or

   Server         Client
   Negotiate #1
                  Option
   Negotiate #2

   ----

   followed by

   Server         Client
B
bellard 已提交
124 125 126 127 128 129 130
                  Request
   Response
                  Request
   Response
                  ...
   ...
                  Request (type == 2)
131

B
bellard 已提交
132 133
*/

134 135 136
/* Send a reply header, including length, but no payload.
 * Return -errno on error, 0 on success. */
static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
137
                                      uint32_t opt, uint32_t len, Error **errp)
138 139 140
{
    uint64_t magic;

141 142
    TRACE("Reply opt=%" PRIx32 " type=%" PRIx32 " len=%" PRIu32,
          type, opt, len);
143

144
    magic = cpu_to_be64(NBD_REP_MAGIC);
145 146
    if (nbd_write(ioc, &magic, sizeof(magic), errp) < 0) {
        error_prepend(errp, "write failed (rep magic): ");
147
        return -EINVAL;
148
    }
149

150
    opt = cpu_to_be32(opt);
151 152
    if (nbd_write(ioc, &opt, sizeof(opt), errp) < 0) {
        error_prepend(errp, "write failed (rep opt): ");
153
        return -EINVAL;
154
    }
155

156
    type = cpu_to_be32(type);
157 158
    if (nbd_write(ioc, &type, sizeof(type), errp) < 0) {
        error_prepend(errp, "write failed (rep type): ");
159
        return -EINVAL;
160
    }
161

162
    len = cpu_to_be32(len);
163 164
    if (nbd_write(ioc, &len, sizeof(len), errp) < 0) {
        error_prepend(errp, "write failed (rep data length): ");
165
        return -EINVAL;
166
    }
167 168
    return 0;
}
169

170 171
/* Send a reply header with default 0 length.
 * Return -errno on error, 0 on success. */
172 173
static int nbd_negotiate_send_rep(QIOChannel *ioc, uint32_t type, uint32_t opt,
                                  Error **errp)
174
{
175
    return nbd_negotiate_send_rep_len(ioc, type, opt, 0, errp);
176 177
}

178 179
/* Send an error reply.
 * Return -errno on error, 0 on success. */
180
static int GCC_FMT_ATTR(5, 6)
181
nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
182
                           uint32_t opt, Error **errp, const char *fmt, ...)
183 184 185 186 187 188 189 190 191 192 193 194
{
    va_list va;
    char *msg;
    int ret;
    size_t len;

    va_start(va, fmt);
    msg = g_strdup_vprintf(fmt, va);
    va_end(va);
    len = strlen(msg);
    assert(len < 4096);
    TRACE("sending error message \"%s\"", msg);
195
    ret = nbd_negotiate_send_rep_len(ioc, type, opt, len, errp);
196 197 198
    if (ret < 0) {
        goto out;
    }
199 200
    if (nbd_write(ioc, msg, len, errp) < 0) {
        error_prepend(errp, "write failed (error message): ");
201 202 203 204
        ret = -EIO;
    } else {
        ret = 0;
    }
205

206 207 208 209 210
out:
    g_free(msg);
    return ret;
}

211 212
/* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
 * Return -errno on error, 0 on success. */
213 214
static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp,
                                       Error **errp)
215
{
216
    size_t name_len, desc_len;
217
    uint32_t len;
218 219
    const char *name = exp->name ? exp->name : "";
    const char *desc = exp->description ? exp->description : "";
220
    int ret;
221

222 223 224
    TRACE("Advertising export name '%s' description '%s'", name, desc);
    name_len = strlen(name);
    desc_len = strlen(desc);
225
    len = name_len + desc_len + sizeof(len);
226 227
    ret = nbd_negotiate_send_rep_len(ioc, NBD_REP_SERVER, NBD_OPT_LIST, len,
                                     errp);
228 229
    if (ret < 0) {
        return ret;
230
    }
231

232
    len = cpu_to_be32(name_len);
233 234
    if (nbd_write(ioc, &len, sizeof(len), errp) < 0) {
        error_prepend(errp, "write failed (name length): ");
235 236
        return -EINVAL;
    }
237 238 239

    if (nbd_write(ioc, name, name_len, errp) < 0) {
        error_prepend(errp, "write failed (name buffer): ");
240 241
        return -EINVAL;
    }
242 243 244

    if (nbd_write(ioc, desc, desc_len, errp) < 0) {
        error_prepend(errp, "write failed (description buffer): ");
245 246
        return -EINVAL;
    }
247

248 249 250
    return 0;
}

251 252
/* Process the NBD_OPT_LIST command, with a potential series of replies.
 * Return -errno on error, 0 on success. */
253 254
static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length,
                                     Error **errp)
255 256 257 258
{
    NBDExport *exp;

    if (length) {
259
        if (nbd_drop(client->ioc, length, errp) < 0) {
260 261
            return -EIO;
        }
262 263
        return nbd_negotiate_send_rep_err(client->ioc,
                                          NBD_REP_ERR_INVALID, NBD_OPT_LIST,
264
                                          errp,
265
                                          "OPT_LIST should not have length");
266 267 268 269
    }

    /* For each export, send a NBD_REP_SERVER reply. */
    QTAILQ_FOREACH(exp, &exports, next) {
270
        if (nbd_negotiate_send_rep_list(client->ioc, exp, errp)) {
271 272 273 274
            return -EINVAL;
        }
    }
    /* Finish with a NBD_REP_ACK. */
275
    return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, NBD_OPT_LIST, errp);
276 277
}

278 279
static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
                                            Error **errp)
280
{
281
    char name[NBD_MAX_NAME_SIZE + 1];
282

283 284 285
    /* Client sends:
        [20 ..  xx]   export name (length bytes)
     */
286
    TRACE("Checking length");
287
    if (length >= sizeof(name)) {
288
        error_setg(errp, "Bad length received");
289
        return -EINVAL;
290
    }
291 292
    if (nbd_read(client->ioc, name, length, errp) < 0) {
        error_prepend(errp, "read failed: ");
293
        return -EINVAL;
294 295 296
    }
    name[length] = '\0';

297 298
    TRACE("Client requested export '%s'", name);

299 300
    client->exp = nbd_export_find(name);
    if (!client->exp) {
301
        error_setg(errp, "export not found");
302
        return -EINVAL;
303 304 305 306
    }

    QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
    nbd_export_get(client->exp);
307 308

    return 0;
309 310
}

311 312
/* Handle NBD_OPT_STARTTLS. Return NULL to drop connection, or else the
 * new channel for all further (now-encrypted) communication. */
313
static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
314 315
                                                 uint32_t length,
                                                 Error **errp)
316 317 318 319 320 321 322 323
{
    QIOChannel *ioc;
    QIOChannelTLS *tioc;
    struct NBDTLSHandshakeData data = { 0 };

    TRACE("Setting up TLS");
    ioc = client->ioc;
    if (length) {
324
        if (nbd_drop(ioc, length, errp) < 0) {
325 326
            return NULL;
        }
327
        nbd_negotiate_send_rep_err(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS,
328
                                   errp,
329
                                   "OPT_STARTTLS should not have length");
330 331 332
        return NULL;
    }

333
    if (nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK,
334
                               NBD_OPT_STARTTLS, errp) < 0) {
335 336
        return NULL;
    }
337 338 339 340

    tioc = qio_channel_tls_new_server(ioc,
                                      client->tlscreds,
                                      client->tlsaclname,
341
                                      errp);
342 343 344 345
    if (!tioc) {
        return NULL;
    }

346
    qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
347 348 349 350 351 352 353 354 355 356 357 358 359
    TRACE("Starting TLS handshake");
    data.loop = g_main_loop_new(g_main_context_default(), FALSE);
    qio_channel_tls_handshake(tioc,
                              nbd_tls_handshake,
                              &data,
                              NULL);

    if (!data.complete) {
        g_main_loop_run(data.loop);
    }
    g_main_loop_unref(data.loop);
    if (data.error) {
        object_unref(OBJECT(tioc));
360
        error_propagate(errp, data.error);
361 362 363 364 365 366
        return NULL;
    }

    return QIO_CHANNEL(tioc);
}

367 368 369
/* nbd_negotiate_options
 * Process all NBD_OPT_* client option commands.
 * Return:
370 371 372 373
 * -errno  on error, errp is set
 * 0       on successful negotiation, errp is not set
 * 1       if client sent NBD_OPT_ABORT, i.e. on valid disconnect,
 *         errp is not set
374
 */
375
static int nbd_negotiate_options(NBDClient *client, Error **errp)
376
{
M
Max Reitz 已提交
377
    uint32_t flags;
378
    bool fixedNewstyle = false;
379
    Error *local_err = NULL;
M
Max Reitz 已提交
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394

    /* Client sends:
        [ 0 ..   3]   client flags

        [ 0 ..   7]   NBD_OPTS_MAGIC
        [ 8 ..  11]   NBD option
        [12 ..  15]   Data length
        ...           Rest of request

        [ 0 ..   7]   NBD_OPTS_MAGIC
        [ 8 ..  11]   Second NBD option
        [12 ..  15]   Data length
        ...           Rest of request
    */

395 396
    if (nbd_read(client->ioc, &flags, sizeof(flags), errp) < 0) {
        error_prepend(errp, "read failed: ");
M
Max Reitz 已提交
397 398 399 400
        return -EIO;
    }
    TRACE("Checking client flags");
    be32_to_cpus(&flags);
401
    if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
402
        TRACE("Client supports fixed newstyle handshake");
403 404 405
        fixedNewstyle = true;
        flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
    }
E
Eric Blake 已提交
406 407 408 409 410
    if (flags & NBD_FLAG_C_NO_ZEROES) {
        TRACE("Client supports no zeroes at handshake end");
        client->no_zeroes = true;
        flags &= ~NBD_FLAG_C_NO_ZEROES;
    }
411
    if (flags != 0) {
412
        error_setg(errp, "Unknown client flags 0x%" PRIx32 " received", flags);
M
Max Reitz 已提交
413 414 415
        return -EIO;
    }

416
    while (1) {
M
Max Reitz 已提交
417
        int ret;
418
        uint32_t clientflags, length;
419 420
        uint64_t magic;

421 422
        if (nbd_read(client->ioc, &magic, sizeof(magic), errp) < 0) {
            error_prepend(errp, "read failed: ");
423 424 425 426
            return -EINVAL;
        }
        TRACE("Checking opts magic");
        if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {
427
            error_setg(errp, "Bad magic received");
428 429 430
            return -EINVAL;
        }

431
        if (nbd_read(client->ioc, &clientflags,
432 433
                     sizeof(clientflags), errp) < 0) {
            error_prepend(errp, "read failed: ");
434 435
            return -EINVAL;
        }
436
        clientflags = be32_to_cpu(clientflags);
437

438 439
        if (nbd_read(client->ioc, &length, sizeof(length), errp) < 0) {
            error_prepend(errp, "read failed: ");
440 441 442 443
            return -EINVAL;
        }
        length = be32_to_cpu(length);

444
        TRACE("Checking option 0x%" PRIx32, clientflags);
445 446 447 448
        if (client->tlscreds &&
            client->ioc == (QIOChannel *)client->sioc) {
            QIOChannel *tioc;
            if (!fixedNewstyle) {
449
                error_setg(errp, "Unsupported option 0x%" PRIx32, clientflags);
450 451 452 453
                return -EINVAL;
            }
            switch (clientflags) {
            case NBD_OPT_STARTTLS:
454
                tioc = nbd_negotiate_handle_starttls(client, length, errp);
455 456 457 458 459 460 461
                if (!tioc) {
                    return -EIO;
                }
                object_unref(OBJECT(client->ioc));
                client->ioc = QIO_CHANNEL(tioc);
                break;

462 463
            case NBD_OPT_EXPORT_NAME:
                /* No way to return an error to client, so drop connection */
464 465
                error_setg(errp, "Option 0x%x not permitted before TLS",
                           clientflags);
466 467
                return -EINVAL;

468
            default:
469
                if (nbd_drop(client->ioc, length, errp) < 0) {
470 471
                    return -EIO;
                }
472 473
                ret = nbd_negotiate_send_rep_err(client->ioc,
                                                 NBD_REP_ERR_TLS_REQD,
474
                                                 clientflags, errp,
475 476 477
                                                 "Option 0x%" PRIx32
                                                 "not permitted before TLS",
                                                 clientflags);
478 479 480
                if (ret < 0) {
                    return ret;
                }
481 482
                /* Let the client keep trying, unless they asked to quit */
                if (clientflags == NBD_OPT_ABORT) {
483
                    return 1;
484
                }
485
                break;
486 487
            }
        } else if (fixedNewstyle) {
488 489
            switch (clientflags) {
            case NBD_OPT_LIST:
490
                ret = nbd_negotiate_handle_list(client, length, errp);
491 492 493 494 495 496
                if (ret < 0) {
                    return ret;
                }
                break;

            case NBD_OPT_ABORT:
497 498 499
                /* NBD spec says we must try to reply before
                 * disconnecting, but that we must also tolerate
                 * guests that don't wait for our reply. */
500 501 502 503 504 505 506 507 508
                nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, clientflags,
                                       &local_err);

                if (local_err != NULL) {
                    TRACE("Reply to NBD_OPT_ABORT request failed: %s",
                          error_get_pretty(local_err));
                    error_free(local_err);
                }

509
                return 1;
510 511

            case NBD_OPT_EXPORT_NAME:
512
                return nbd_negotiate_handle_export_name(client, length, errp);
513

514
            case NBD_OPT_STARTTLS:
515
                if (nbd_drop(client->ioc, length, errp) < 0) {
516 517
                    return -EIO;
                }
518
                if (client->tlscreds) {
519 520
                    ret = nbd_negotiate_send_rep_err(client->ioc,
                                                     NBD_REP_ERR_INVALID,
521
                                                     clientflags, errp,
522
                                                     "TLS already enabled");
523
                } else {
524 525
                    ret = nbd_negotiate_send_rep_err(client->ioc,
                                                     NBD_REP_ERR_POLICY,
526
                                                     clientflags, errp,
527
                                                     "TLS not configured");
528 529 530
                }
                if (ret < 0) {
                    return ret;
531
                }
532
                break;
533
            default:
534
                if (nbd_drop(client->ioc, length, errp) < 0) {
535 536
                    return -EIO;
                }
537 538
                ret = nbd_negotiate_send_rep_err(client->ioc,
                                                 NBD_REP_ERR_UNSUP,
539
                                                 clientflags, errp,
540 541 542
                                                 "Unsupported option 0x%"
                                                 PRIx32,
                                                 clientflags);
543 544 545
                if (ret < 0) {
                    return ret;
                }
546
                break;
547 548 549 550 551 552 553 554
            }
        } else {
            /*
             * If broken new-style we should drop the connection
             * for anything except NBD_OPT_EXPORT_NAME
             */
            switch (clientflags) {
            case NBD_OPT_EXPORT_NAME:
555
                return nbd_negotiate_handle_export_name(client, length, errp);
556 557

            default:
558
                error_setg(errp, "Unsupported option 0x%" PRIx32, clientflags);
559
                return -EINVAL;
560
            }
561 562 563 564
        }
    }
}

565 566
/* nbd_negotiate
 * Return:
567 568 569 570
 * -errno  on error, errp is set
 * 0       on successful negotiation, errp is not set
 * 1       if client sent NBD_OPT_ABORT, i.e. on valid disconnect,
 *         errp is not set
571
 */
572
static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
B
bellard 已提交
573
{
N
Nick Thomas 已提交
574
    char buf[8 + 8 + 8 + 128];
575
    int ret;
E
Eric Blake 已提交
576
    const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
577 578
                              NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
                              NBD_FLAG_SEND_WRITE_ZEROES);
579
    bool oldStyle;
E
Eric Blake 已提交
580
    size_t len;
N
Nick Thomas 已提交
581

582
    /* Old style negotiation header without options
583 584
        [ 0 ..   7]   passwd       ("NBDMAGIC")
        [ 8 ..  15]   magic        (NBD_CLIENT_MAGIC)
N
Nick Thomas 已提交
585
        [16 ..  23]   size
586
        [24 ..  25]   server flags (0)
H
Hani Benhabiles 已提交
587
        [26 ..  27]   export flags
588 589
        [28 .. 151]   reserved     (0)

590
       New style negotiation header with options
591 592 593
        [ 0 ..   7]   passwd       ("NBDMAGIC")
        [ 8 ..  15]   magic        (NBD_OPTS_MAGIC)
        [16 ..  17]   server flags (0)
594
        ....options sent....
595 596
        [18 ..  25]   size
        [26 ..  27]   export flags
E
Eric Blake 已提交
597
        [28 .. 151]   reserved     (0, omit if no_zeroes)
N
Nick Thomas 已提交
598 599
     */

600
    qio_channel_set_blocking(client->ioc, false, NULL);
601

N
Nick Thomas 已提交
602
    TRACE("Beginning negotiation.");
603
    memset(buf, 0, sizeof(buf));
N
Nick Thomas 已提交
604
    memcpy(buf, "NBDMAGIC", 8);
605 606 607

    oldStyle = client->exp != NULL && !client->tlscreds;
    if (oldStyle) {
608 609
        TRACE("advertising size %" PRIu64 " and flags %x",
              client->exp->size, client->exp->nbdflags | myflags);
J
John Snow 已提交
610 611 612
        stq_be_p(buf + 8, NBD_CLIENT_MAGIC);
        stq_be_p(buf + 16, client->exp->size);
        stw_be_p(buf + 26, client->exp->nbdflags | myflags);
N
Nick Thomas 已提交
613

614 615
        if (nbd_write(client->ioc, buf, sizeof(buf), errp) < 0) {
            error_prepend(errp, "write failed: ");
616
            return -EINVAL;
617 618
        }
    } else {
619 620 621
        stq_be_p(buf + 8, NBD_OPTS_MAGIC);
        stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES);

622 623
        if (nbd_write(client->ioc, buf, 18, errp) < 0) {
            error_prepend(errp, "write failed: ");
624
            return -EINVAL;
625
        }
626
        ret = nbd_negotiate_options(client, errp);
627
        if (ret != 0) {
628 629 630
            if (ret < 0) {
                error_prepend(errp, "option negotiation failed: ");
            }
631
            return ret;
632 633
        }

634 635
        TRACE("advertising size %" PRIu64 " and flags %x",
              client->exp->size, client->exp->nbdflags | myflags);
J
John Snow 已提交
636 637
        stq_be_p(buf + 18, client->exp->size);
        stw_be_p(buf + 26, client->exp->nbdflags | myflags);
E
Eric Blake 已提交
638
        len = client->no_zeroes ? 10 : sizeof(buf) - 18;
639
        ret = nbd_write(client->ioc, buf + 18, len, errp);
640
        if (ret < 0) {
641
            error_prepend(errp, "write failed: ");
642
            return ret;
643
        }
N
Nick Thomas 已提交
644 645
    }

D
Dong Xu Wang 已提交
646
    TRACE("Negotiation succeeded.");
647 648

    return 0;
B
bellard 已提交
649 650
}

651 652
static int nbd_receive_request(QIOChannel *ioc, NBDRequest *request,
                               Error **errp)
653
{
P
Paolo Bonzini 已提交
654
    uint8_t buf[NBD_REQUEST_SIZE];
N
Nick Thomas 已提交
655
    uint32_t magic;
656
    int ret;
N
Nick Thomas 已提交
657

658
    ret = nbd_read(ioc, buf, sizeof(buf), errp);
659 660 661 662
    if (ret < 0) {
        return ret;
    }

N
Nick Thomas 已提交
663 664
    /* Request
       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
665 666
       [ 4 ..  5]   flags   (NBD_CMD_FLAG_FUA, ...)
       [ 6 ..  7]   type    (NBD_CMD_READ, ...)
N
Nick Thomas 已提交
667 668 669 670 671
       [ 8 .. 15]   handle
       [16 .. 23]   from
       [24 .. 27]   len
     */

672
    magic = ldl_be_p(buf);
673 674
    request->flags  = lduw_be_p(buf + 4);
    request->type   = lduw_be_p(buf + 6);
675 676 677
    request->handle = ldq_be_p(buf + 8);
    request->from   = ldq_be_p(buf + 16);
    request->len    = ldl_be_p(buf + 24);
N
Nick Thomas 已提交
678

679 680 681
    TRACE("Got request: { magic = 0x%" PRIx32 ", .flags = %" PRIx16
          ", .type = %" PRIx16 ", from = %" PRIu64 ", len = %" PRIu32 " }",
          magic, request->flags, request->type, request->from, request->len);
N
Nick Thomas 已提交
682 683

    if (magic != NBD_REQUEST_MAGIC) {
684
        error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic);
685
        return -EINVAL;
N
Nick Thomas 已提交
686 687
    }
    return 0;
688 689
}

690
static int nbd_send_reply(QIOChannel *ioc, NBDReply *reply)
691
{
P
Paolo Bonzini 已提交
692
    uint8_t buf[NBD_REPLY_SIZE];
N
Nick Thomas 已提交
693

694 695
    reply->error = system_errno_to_nbd_errno(reply->error);

696 697
    TRACE("Sending response to client: { .error = %" PRId32
          ", handle = %" PRIu64 " }",
698 699
          reply->error, reply->handle);

N
Nick Thomas 已提交
700 701 702 703 704
    /* Reply
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
       [ 4 ..  7]    error   (0 == no error)
       [ 7 .. 15]    handle
     */
J
John Snow 已提交
705 706 707
    stl_be_p(buf, NBD_REPLY_MAGIC);
    stl_be_p(buf + 4, reply->error);
    stq_be_p(buf + 8, reply->handle);
N
Nick Thomas 已提交
708

709
    return nbd_write(ioc, buf, sizeof(buf), NULL);
710
}
B
bellard 已提交
711

P
Paolo Bonzini 已提交
712 713
#define MAX_NBD_REQUESTS 16

714
void nbd_client_get(NBDClient *client)
715 716 717 718
{
    client->refcount++;
}

719
void nbd_client_put(NBDClient *client)
720 721
{
    if (--client->refcount == 0) {
722
        /* The last reference should be dropped by client->close,
M
Max Reitz 已提交
723
         * which is called by client_close.
724 725 726
         */
        assert(client->closing);

727
        qio_channel_detach_aio_context(client->ioc);
728 729
        object_unref(OBJECT(client->sioc));
        object_unref(OBJECT(client->ioc));
730 731 732 733
        if (client->tlscreds) {
            object_unref(OBJECT(client->tlscreds));
        }
        g_free(client->tlsaclname);
734 735 736 737
        if (client->exp) {
            QTAILQ_REMOVE(&client->exp->clients, client, next);
            nbd_export_put(client->exp);
        }
738 739 740 741
        g_free(client);
    }
}

742
static void client_close(NBDClient *client, bool negotiated)
743
{
744 745 746 747 748 749 750 751 752
    if (client->closing) {
        return;
    }

    client->closing = true;

    /* Force requests to finish.  They will drop their own references,
     * then we'll close the socket and free the NBDClient.
     */
753 754
    qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH,
                         NULL);
755 756

    /* Also tell the client, so that they release their reference.  */
757 758
    if (client->close_fn) {
        client->close_fn(client, negotiated);
759 760 761
    }
}

762
static NBDRequestData *nbd_request_get(NBDClient *client)
P
Paolo Bonzini 已提交
763
{
764
    NBDRequestData *req;
765

P
Paolo Bonzini 已提交
766 767 768
    assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
    client->nb_requests++;

769
    req = g_new0(NBDRequestData, 1);
770 771
    nbd_client_get(client);
    req->client = client;
P
Paolo Bonzini 已提交
772 773 774
    return req;
}

775
static void nbd_request_put(NBDRequestData *req)
P
Paolo Bonzini 已提交
776
{
777
    NBDClient *client = req->client;
778

779 780 781
    if (req->data) {
        qemu_vfree(req->data);
    }
782
    g_free(req);
783

M
Max Reitz 已提交
784
    client->nb_requests--;
785 786
    nbd_client_receive_next_request(client);

787
    nbd_client_put(client);
P
Paolo Bonzini 已提交
788 789
}

M
Max Reitz 已提交
790
static void blk_aio_attached(AioContext *ctx, void *opaque)
M
Max Reitz 已提交
791 792 793 794 795 796 797 798 799
{
    NBDExport *exp = opaque;
    NBDClient *client;

    TRACE("Export %s: Attaching clients to AIO context %p\n", exp->name, ctx);

    exp->ctx = ctx;

    QTAILQ_FOREACH(client, &exp->clients, next) {
800 801 802 803 804 805 806
        qio_channel_attach_aio_context(client->ioc, ctx);
        if (client->recv_coroutine) {
            aio_co_schedule(ctx, client->recv_coroutine);
        }
        if (client->send_coroutine) {
            aio_co_schedule(ctx, client->send_coroutine);
        }
M
Max Reitz 已提交
807 808 809
    }
}

M
Max Reitz 已提交
810
static void blk_aio_detach(void *opaque)
M
Max Reitz 已提交
811 812 813 814 815 816 817
{
    NBDExport *exp = opaque;
    NBDClient *client;

    TRACE("Export %s: Detaching clients from AIO context %p\n", exp->name, exp->ctx);

    QTAILQ_FOREACH(client, &exp->clients, next) {
818
        qio_channel_detach_aio_context(client->ioc);
M
Max Reitz 已提交
819 820 821 822 823
    }

    exp->ctx = NULL;
}

824 825 826 827 828 829
static void nbd_eject_notifier(Notifier *n, void *data)
{
    NBDExport *exp = container_of(n, NBDExport, eject_notifier);
    nbd_export_close(exp);
}

830
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
E
Eric Blake 已提交
831
                          uint16_t nbdflags, void (*close)(NBDExport *),
832
                          bool writethrough, BlockBackend *on_eject_blk,
M
Max Reitz 已提交
833
                          Error **errp)
P
Paolo Bonzini 已提交
834
{
835
    BlockBackend *blk;
P
Paolo Bonzini 已提交
836
    NBDExport *exp = g_malloc0(sizeof(NBDExport));
837
    uint64_t perm;
838
    int ret;
839

840 841 842 843 844 845 846 847
    /* Don't allow resize while the NBD server is running, otherwise we don't
     * care what happens with the node. */
    perm = BLK_PERM_CONSISTENT_READ;
    if ((nbdflags & NBD_FLAG_READ_ONLY) == 0) {
        perm |= BLK_PERM_WRITE;
    }
    blk = blk_new(perm, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
                        BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD);
848 849 850 851
    ret = blk_insert_bs(blk, bs, errp);
    if (ret < 0) {
        goto fail;
    }
852 853
    blk_set_enable_write_cache(blk, !writethrough);

854
    exp->refcount = 1;
855
    QTAILQ_INIT(&exp->clients);
M
Max Reitz 已提交
856
    exp->blk = blk;
P
Paolo Bonzini 已提交
857 858
    exp->dev_offset = dev_offset;
    exp->nbdflags = nbdflags;
M
Max Reitz 已提交
859 860 861 862 863 864 865 866
    exp->size = size < 0 ? blk_getlength(blk) : size;
    if (exp->size < 0) {
        error_setg_errno(errp, -exp->size,
                         "Failed to determine the NBD export's length");
        goto fail;
    }
    exp->size -= exp->size % BDRV_SECTOR_SIZE;

867
    exp->close = close;
M
Max Reitz 已提交
868 869
    exp->ctx = blk_get_aio_context(blk);
    blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
870

871 872 873 874 875 876
    if (on_eject_blk) {
        blk_ref(on_eject_blk);
        exp->eject_notifier_blk = on_eject_blk;
        exp->eject_notifier.notify = nbd_eject_notifier;
        blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier);
    }
877

878 879
    /*
     * NBD exports are used for non-shared storage migration.  Make sure
880
     * that BDRV_O_INACTIVE is cleared and the image is ready for write
881 882
     * access since the export could be available before migration handover.
     */
883
    aio_context_acquire(exp->ctx);
M
Max Reitz 已提交
884
    blk_invalidate_cache(blk, NULL);
885
    aio_context_release(exp->ctx);
P
Paolo Bonzini 已提交
886
    return exp;
M
Max Reitz 已提交
887 888

fail:
889
    blk_unref(blk);
M
Max Reitz 已提交
890 891
    g_free(exp);
    return NULL;
P
Paolo Bonzini 已提交
892 893
}

P
Paolo Bonzini 已提交
894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
NBDExport *nbd_export_find(const char *name)
{
    NBDExport *exp;
    QTAILQ_FOREACH(exp, &exports, next) {
        if (strcmp(name, exp->name) == 0) {
            return exp;
        }
    }

    return NULL;
}

void nbd_export_set_name(NBDExport *exp, const char *name)
{
    if (exp->name == name) {
        return;
    }

    nbd_export_get(exp);
    if (exp->name != NULL) {
        g_free(exp->name);
        exp->name = NULL;
        QTAILQ_REMOVE(&exports, exp, next);
        nbd_export_put(exp);
    }
    if (name != NULL) {
        nbd_export_get(exp);
        exp->name = g_strdup(name);
        QTAILQ_INSERT_TAIL(&exports, exp, next);
    }
    nbd_export_put(exp);
}

927 928 929 930 931 932
void nbd_export_set_description(NBDExport *exp, const char *description)
{
    g_free(exp->description);
    exp->description = g_strdup(description);
}

P
Paolo Bonzini 已提交
933 934
void nbd_export_close(NBDExport *exp)
{
935
    NBDClient *client, *next;
936

937 938
    nbd_export_get(exp);
    QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
939
        client_close(client, true);
940
    }
P
Paolo Bonzini 已提交
941
    nbd_export_set_name(exp, NULL);
942
    nbd_export_set_description(exp, NULL);
943
    nbd_export_put(exp);
944 945 946 947 948 949 950 951 952 953 954 955 956
}

void nbd_export_get(NBDExport *exp)
{
    assert(exp->refcount > 0);
    exp->refcount++;
}

void nbd_export_put(NBDExport *exp)
{
    assert(exp->refcount > 0);
    if (exp->refcount == 1) {
        nbd_export_close(exp);
P
Paolo Bonzini 已提交
957 958
    }

959
    if (--exp->refcount == 0) {
P
Paolo Bonzini 已提交
960
        assert(exp->name == NULL);
961
        assert(exp->description == NULL);
P
Paolo Bonzini 已提交
962

963 964 965 966
        if (exp->close) {
            exp->close(exp);
        }

967
        if (exp->blk) {
968 969 970 971
            if (exp->eject_notifier_blk) {
                notifier_remove(&exp->eject_notifier);
                blk_unref(exp->eject_notifier_blk);
            }
972 973 974 975 976 977
            blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
                                            blk_aio_detach, exp);
            blk_unref(exp->blk);
            exp->blk = NULL;
        }

978 979
        g_free(exp);
    }
P
Paolo Bonzini 已提交
980 981
}

982
BlockBackend *nbd_export_get_blockdev(NBDExport *exp)
P
Paolo Bonzini 已提交
983
{
M
Max Reitz 已提交
984
    return exp->blk;
P
Paolo Bonzini 已提交
985 986
}

P
Paolo Bonzini 已提交
987 988 989 990 991 992 993 994 995
void nbd_export_close_all(void)
{
    NBDExport *exp, *next;

    QTAILQ_FOREACH_SAFE(exp, &exports, next, next) {
        nbd_export_close(exp);
    }
}

996
static int nbd_co_send_reply(NBDRequestData *req, NBDReply *reply, int len)
997
{
998
    NBDClient *client = req->client;
999
    int ret;
1000

1001
    g_assert(qemu_in_coroutine());
P
Paolo Bonzini 已提交
1002 1003 1004
    qemu_co_mutex_lock(&client->send_lock);
    client->send_coroutine = qemu_coroutine_self();

1005
    if (!len) {
1006
        ret = nbd_send_reply(client->ioc, reply);
1007
    } else {
1008
        qio_channel_set_cork(client->ioc, true);
1009 1010 1011 1012 1013
        ret = nbd_send_reply(client->ioc, reply);
        if (ret == 0) {
            ret = nbd_write(client->ioc, req->data, len, NULL);
            if (ret < 0) {
                ret = -EIO;
1014 1015
            }
        }
1016
        qio_channel_set_cork(client->ioc, false);
1017
    }
P
Paolo Bonzini 已提交
1018 1019 1020

    client->send_coroutine = NULL;
    qemu_co_mutex_unlock(&client->send_lock);
1021
    return ret;
1022 1023
}

1024 1025 1026 1027 1028 1029
/* nbd_co_receive_request
 * Collect a client request. Return 0 if request looks valid, -EIO to drop
 * connection right away, and any other negative value to report an error to
 * the client (although the caller may still need to disconnect after reporting
 * the error).
 */
1030 1031
static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
                                  Error **errp)
1032
{
1033
    NBDClient *client = req->client;
1034

1035
    g_assert(qemu_in_coroutine());
1036
    assert(client->recv_coroutine == qemu_coroutine_self());
1037
    if (nbd_receive_request(client->ioc, request, errp) < 0) {
1038
        return -EIO;
1039 1040
    }

1041 1042
    TRACE("Decoding type");

1043
    if (request->type != NBD_CMD_WRITE) {
1044 1045 1046 1047
        /* No payload, we are ready to read the next request.  */
        req->complete = true;
    }

1048
    if (request->type == NBD_CMD_DISC) {
1049 1050 1051
        /* Special case: we're going to disconnect without a reply,
         * whether or not flags, from, or len are bogus */
        TRACE("Request type is DISCONNECT");
1052
        return -EIO;
1053 1054 1055 1056 1057
    }

    /* Check for sanity in the parameters, part 1.  Defer as many
     * checks as possible until after reading any NBD_CMD_WRITE
     * payload, so we can try and keep the connection alive.  */
1058
    if ((request->from + request->len) < request->from) {
1059 1060
        error_setg(errp,
                   "integer overflow detected, you're probably being attacked");
1061
        return -EINVAL;
1062 1063
    }

1064
    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE) {
1065
        if (request->len > NBD_MAX_BUFFER_SIZE) {
1066 1067
            error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
                       request->len, NBD_MAX_BUFFER_SIZE);
1068
            return -EINVAL;
1069 1070
        }

1071 1072
        req->data = blk_try_blockalign(client->exp->blk, request->len);
        if (req->data == NULL) {
1073
            error_setg(errp, "No memory");
1074
            return -ENOMEM;
1075
        }
1076
    }
1077
    if (request->type == NBD_CMD_WRITE) {
1078
        TRACE("Reading %" PRIu32 " byte(s)", request->len);
1079

1080 1081
        if (nbd_read(client->ioc, req->data, request->len, errp) < 0) {
            error_prepend(errp, "reading from socket failed: ");
1082
            return -EIO;
1083
        }
1084
        req->complete = true;
1085
    }
1086 1087 1088

    /* Sanity checks, part 2. */
    if (request->from + request->len > client->exp->size) {
1089 1090 1091
        error_setg(errp, "operation past EOF; From: %" PRIu64 ", Len: %" PRIu32
                   ", Size: %" PRIu64, request->from, request->len,
                   (uint64_t)client->exp->size);
1092
        return request->type == NBD_CMD_WRITE ? -ENOSPC : -EINVAL;
1093
    }
1094
    if (request->flags & ~(NBD_CMD_FLAG_FUA | NBD_CMD_FLAG_NO_HOLE)) {
1095
        error_setg(errp, "unsupported flags (got 0x%x)", request->flags);
1096
        return -EINVAL;
E
Eric Blake 已提交
1097
    }
1098 1099
    if (request->type != NBD_CMD_WRITE_ZEROES &&
        (request->flags & NBD_CMD_FLAG_NO_HOLE)) {
1100
        error_setg(errp, "unexpected flags (got 0x%x)", request->flags);
1101
        return -EINVAL;
1102
    }
1103

1104
    return 0;
1105 1106
}

1107 1108
/* Owns a reference to the NBDClient passed as opaque.  */
static coroutine_fn void nbd_trip(void *opaque)
1109
{
P
Paolo Bonzini 已提交
1110
    NBDClient *client = opaque;
1111
    NBDExport *exp = client->exp;
1112
    NBDRequestData *req;
1113
    NBDRequest request = { 0 };    /* GCC thinks it can be used uninitialized */
1114
    NBDReply reply;
1115
    int ret;
1116
    int flags;
1117
    int reply_data_len = 0;
1118
    Error *local_err = NULL;
N
Nick Thomas 已提交
1119 1120

    TRACE("Reading request.");
1121
    if (client->closing) {
1122
        nbd_client_put(client);
1123 1124
        return;
    }
N
Nick Thomas 已提交
1125

1126
    req = nbd_request_get(client);
1127
    ret = nbd_co_receive_request(req, &request, &local_err);
1128 1129
    client->recv_coroutine = NULL;
    nbd_client_receive_next_request(client);
1130
    if (ret == -EIO) {
1131
        goto disconnect;
1132
    }
N
Nick Thomas 已提交
1133

1134 1135 1136
    reply.handle = request.handle;
    reply.error = 0;

1137 1138
    if (ret < 0) {
        reply.error = -ret;
1139
        goto reply;
N
Nick Thomas 已提交
1140 1141
    }

1142 1143 1144 1145 1146 1147 1148 1149
    if (client->closing) {
        /*
         * The client may be closed when we are blocked in
         * nbd_co_receive_request()
         */
        goto done;
    }

1150
    switch (request.type) {
N
Nick Thomas 已提交
1151 1152 1153
    case NBD_CMD_READ:
        TRACE("Request type is READ");

1154 1155
        /* XXX: NBD Protocol only documents use of FUA with WRITE */
        if (request.flags & NBD_CMD_FLAG_FUA) {
M
Max Reitz 已提交
1156
            ret = blk_co_flush(exp->blk);
P
Paolo Bonzini 已提交
1157
            if (ret < 0) {
1158
                error_setg_errno(&local_err, -ret, "flush failed");
P
Paolo Bonzini 已提交
1159
                reply.error = -ret;
1160
                break;
P
Paolo Bonzini 已提交
1161 1162 1163
            }
        }

1164 1165
        ret = blk_pread(exp->blk, request.from + exp->dev_offset,
                        req->data, request.len);
1166
        if (ret < 0) {
1167
            error_setg_errno(&local_err, -ret, "reading from file failed");
1168
            reply.error = -ret;
1169
            break;
N
Nick Thomas 已提交
1170 1171
        }

1172
        reply_data_len = request.len;
1173
        TRACE("Read %" PRIu32" byte(s)", request.len);
1174

N
Nick Thomas 已提交
1175 1176 1177 1178
        break;
    case NBD_CMD_WRITE:
        TRACE("Request type is WRITE");

P
Paolo Bonzini 已提交
1179
        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
N
Nick Thomas 已提交
1180
            TRACE("Server is read-only, return error");
1181
            reply.error = EROFS;
1182
            break;
1183 1184 1185 1186
        }

        TRACE("Writing to device");

1187
        flags = 0;
1188
        if (request.flags & NBD_CMD_FLAG_FUA) {
1189 1190
            flags |= BDRV_REQ_FUA;
        }
1191
        ret = blk_pwrite(exp->blk, request.from + exp->dev_offset,
1192
                         req->data, request.len, flags);
1193
        if (ret < 0) {
1194
            error_setg_errno(&local_err, -ret, "writing to file failed");
1195 1196
            reply.error = -ret;
        }
N
Nick Thomas 已提交
1197

1198 1199 1200 1201 1202
        break;
    case NBD_CMD_WRITE_ZEROES:
        TRACE("Request type is WRITE_ZEROES");

        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
1203
            error_setg(&local_err, "Server is read-only, return error");
1204
            reply.error = EROFS;
1205
            break;
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
        }

        TRACE("Writing to device");

        flags = 0;
        if (request.flags & NBD_CMD_FLAG_FUA) {
            flags |= BDRV_REQ_FUA;
        }
        if (!(request.flags & NBD_CMD_FLAG_NO_HOLE)) {
            flags |= BDRV_REQ_MAY_UNMAP;
        }
        ret = blk_pwrite_zeroes(exp->blk, request.from + exp->dev_offset,
                                request.len, flags);
        if (ret < 0) {
1220
            error_setg_errno(&local_err, -ret, "writing to file failed");
1221 1222 1223
            reply.error = -ret;
        }

N
Nick Thomas 已提交
1224 1225
        break;
    case NBD_CMD_DISC:
1226 1227 1228
        /* unreachable, thanks to special case in nbd_co_receive_request() */
        abort();

P
Paolo Bonzini 已提交
1229 1230 1231
    case NBD_CMD_FLUSH:
        TRACE("Request type is FLUSH");

M
Max Reitz 已提交
1232
        ret = blk_co_flush(exp->blk);
P
Paolo Bonzini 已提交
1233
        if (ret < 0) {
1234
            error_setg_errno(&local_err, -ret, "flush failed");
P
Paolo Bonzini 已提交
1235 1236
            reply.error = -ret;
        }
1237

P
Paolo Bonzini 已提交
1238 1239 1240
        break;
    case NBD_CMD_TRIM:
        TRACE("Request type is TRIM");
1241 1242 1243
        ret = blk_co_pdiscard(exp->blk, request.from + exp->dev_offset,
                              request.len);
        if (ret < 0) {
1244
            error_setg_errno(&local_err, -ret, "discard failed");
1245
            reply.error = -ret;
P
Paolo Bonzini 已提交
1246
        }
1247

P
Paolo Bonzini 已提交
1248
        break;
N
Nick Thomas 已提交
1249
    default:
1250 1251
        error_setg(&local_err, "invalid request type (%" PRIu32 ") received",
                   request.type);
Y
Yik Fang 已提交
1252
        reply.error = EINVAL;
1253 1254 1255
    }

reply:
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
    if (local_err) {
        /* If we are here local_err is not fatal error, already stored in
         * reply.error */
        error_report_err(local_err);
        local_err = NULL;
    }

    if (nbd_co_send_reply(req, &reply, reply_data_len) < 0) {
        error_setg(&local_err, "Failed to send reply");
        goto disconnect;
    }

1268 1269 1270
    /* We must disconnect after NBD_CMD_WRITE if we did not
     * read the payload.
     */
1271 1272
    if (!req->complete) {
        error_setg(&local_err, "Request handling failed in intermediate state");
1273
        goto disconnect;
N
Nick Thomas 已提交
1274 1275 1276 1277
    }

    TRACE("Request/Reply complete");

1278
done:
P
Paolo Bonzini 已提交
1279
    nbd_request_put(req);
1280
    nbd_client_put(client);
P
Paolo Bonzini 已提交
1281 1282
    return;

1283
disconnect:
1284 1285 1286
    if (local_err) {
        error_reportf_err(local_err, "Disconnect client, due to: ");
    }
1287
    nbd_request_put(req);
1288
    client_close(client, true);
1289
    nbd_client_put(client);
B
bellard 已提交
1290
}
P
Paolo Bonzini 已提交
1291

1292
static void nbd_client_receive_next_request(NBDClient *client)
M
Max Reitz 已提交
1293
{
1294 1295 1296 1297
    if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS) {
        nbd_client_get(client);
        client->recv_coroutine = qemu_coroutine_create(nbd_trip, client);
        aio_co_schedule(client->exp->ctx, client->recv_coroutine);
M
Max Reitz 已提交
1298 1299 1300
    }
}

1301 1302
static coroutine_fn void nbd_co_client_start(void *opaque)
{
1303
    NBDClient *client = opaque;
1304
    NBDExport *exp = client->exp;
1305
    Error *local_err = NULL;
1306 1307 1308

    if (exp) {
        nbd_export_get(exp);
1309
        QTAILQ_INSERT_TAIL(&exp->clients, client, next);
1310
    }
1311 1312
    qemu_co_mutex_init(&client->send_lock);

1313 1314 1315 1316
    if (nbd_negotiate(client, &local_err)) {
        if (local_err) {
            error_report_err(local_err);
        }
1317
        client_close(client, false);
1318
        return;
1319
    }
1320 1321

    nbd_client_receive_next_request(client);
1322 1323
}

1324 1325 1326 1327 1328 1329
/*
 * Create a new client listener on the given export @exp, using the
 * given channel @sioc.  Begin servicing it in a coroutine.  When the
 * connection closes, call @close_fn with an indication of whether the
 * client completed negotiation.
 */
1330 1331
void nbd_client_new(NBDExport *exp,
                    QIOChannelSocket *sioc,
1332 1333
                    QCryptoTLSCreds *tlscreds,
                    const char *tlsaclname,
1334
                    void (*close_fn)(NBDClient *, bool))
P
Paolo Bonzini 已提交
1335
{
1336
    NBDClient *client;
1337
    Coroutine *co;
1338

1339 1340 1341
    client = g_malloc0(sizeof(NBDClient));
    client->refcount = 1;
    client->exp = exp;
1342 1343 1344 1345 1346
    client->tlscreds = tlscreds;
    if (tlscreds) {
        object_ref(OBJECT(client->tlscreds));
    }
    client->tlsaclname = g_strdup(tlsaclname);
1347 1348 1349 1350
    client->sioc = sioc;
    object_ref(OBJECT(client->sioc));
    client->ioc = QIO_CHANNEL(sioc);
    object_ref(OBJECT(client->ioc));
1351
    client->close_fn = close_fn;
1352

1353 1354
    co = qemu_coroutine_create(nbd_co_client_start, client);
    qemu_coroutine_enter(co);
P
Paolo Bonzini 已提交
1355
}