server.c 38.3 KB
Newer Older
1
/*
2
 *  Copyright (C) 2016-2017 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"
22
#include "trace.h"
F
Fam Zheng 已提交
23
#include "nbd-internal.h"
24 25 26 27 28 29 30

static int system_errno_to_nbd_errno(int err)
{
    switch (err) {
    case 0:
        return NBD_SUCCESS;
    case EPERM:
31
    case EROFS:
32 33 34 35 36 37 38 39 40 41 42
        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;
43 44
    case ESHUTDOWN:
        return NBD_ESHUTDOWN;
45 46 47 48 49 50
    case EINVAL:
    default:
        return NBD_EINVAL;
    }
}

51 52
/* Definitions for opaque data types */

53
typedef struct NBDRequestData NBDRequestData;
54

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

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

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

    AioContext *ctx;
76

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

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

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

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

    Coroutine *recv_coroutine;

    CoMutex send_lock;
    Coroutine *send_coroutine;

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

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

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

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

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

   or

   Server         Client
   Negotiate #1
                  Option
   Negotiate #2

   ----

   followed by

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

B
bellard 已提交
133 134
*/

135 136 137
/* 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,
138
                                      uint32_t opt, uint32_t len, Error **errp)
139 140 141
{
    uint64_t magic;

142 143
    trace_nbd_negotiate_send_rep_len(opt, nbd_opt_lookup(opt),
                                     type, nbd_rep_lookup(type), len);
144

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

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

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

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

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

179 180
/* Send an error reply.
 * Return -errno on error, 0 on success. */
181
static int GCC_FMT_ATTR(5, 6)
182
nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
183
                           uint32_t opt, Error **errp, const char *fmt, ...)
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);
195
    trace_nbd_negotiate_send_rep_err(msg);
196
    ret = nbd_negotiate_send_rep_len(ioc, type, opt, len, errp);
197 198 199
    if (ret < 0) {
        goto out;
    }
200 201
    if (nbd_write(ioc, msg, len, errp) < 0) {
        error_prepend(errp, "write failed (error message): ");
202 203 204 205
        ret = -EIO;
    } else {
        ret = 0;
    }
206

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

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

223
    trace_nbd_negotiate_send_rep_list(name, desc);
224 225
    name_len = strlen(name);
    desc_len = strlen(desc);
226
    len = name_len + desc_len + sizeof(len);
227 228
    ret = nbd_negotiate_send_rep_len(ioc, NBD_REP_SERVER, NBD_OPT_LIST, len,
                                     errp);
229 230
    if (ret < 0) {
        return ret;
231
    }
232

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

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

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

249 250 251
    return 0;
}

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

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

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

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

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

298
    trace_nbd_negotiate_handle_export_name_request(name);
299

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

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

    return 0;
310 311
}

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

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

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

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

347
    qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
348
    trace_nbd_negotiate_handle_starttls_handshake();
349 350 351 352 353 354 355 356 357 358 359 360
    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));
361
        error_propagate(errp, data.error);
362 363 364 365 366 367
        return NULL;
    }

    return QIO_CHANNEL(tioc);
}

368 369 370
/* nbd_negotiate_options
 * Process all NBD_OPT_* client option commands.
 * Return:
371 372 373 374
 * -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
375
 */
376
static int nbd_negotiate_options(NBDClient *client, Error **errp)
377
{
M
Max Reitz 已提交
378
    uint32_t flags;
379
    bool fixedNewstyle = false;
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
        return -EIO;
    }
    be32_to_cpus(&flags);
400
    trace_nbd_negotiate_options_flags(flags);
401 402 403 404
    if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
        fixedNewstyle = true;
        flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
    }
E
Eric Blake 已提交
405 406 407 408
    if (flags & NBD_FLAG_C_NO_ZEROES) {
        client->no_zeroes = true;
        flags &= ~NBD_FLAG_C_NO_ZEROES;
    }
409
    if (flags != 0) {
410
        error_setg(errp, "Unknown client flags 0x%" PRIx32 " received", flags);
411
        return -EINVAL;
M
Max Reitz 已提交
412 413
    }

414
    while (1) {
M
Max Reitz 已提交
415
        int ret;
416
        uint32_t option, length;
417 418
        uint64_t magic;

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

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

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

443 444
        trace_nbd_negotiate_options_check_option(option,
                                                 nbd_opt_lookup(option));
445 446 447 448
        if (client->tlscreds &&
            client->ioc == (QIOChannel *)client->sioc) {
            QIOChannel *tioc;
            if (!fixedNewstyle) {
449
                error_setg(errp, "Unsupported option 0x%" PRIx32, option);
450 451
                return -EINVAL;
            }
452
            switch (option) {
453
            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
                error_setg(errp, "Option 0x%x not permitted before TLS",
465
                           option);
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
                                                 option, errp,
475 476
                                                 "Option 0x%" PRIx32
                                                 "not permitted before TLS",
477
                                                 option);
478 479 480
                if (ret < 0) {
                    return ret;
                }
481 482 483
                /* Let the client keep trying, unless they asked to
                 * quit. In this mode, we've already sent an error, so
                 * we can't ack the abort.  */
484
                if (option == NBD_OPT_ABORT) {
485
                    return 1;
486
                }
487
                break;
488 489
            }
        } else if (fixedNewstyle) {
490
            switch (option) {
491
            case NBD_OPT_LIST:
492
                ret = nbd_negotiate_handle_list(client, length, errp);
493 494 495 496 497 498
                if (ret < 0) {
                    return ret;
                }
                break;

            case NBD_OPT_ABORT:
499 500 501
                /* NBD spec says we must try to reply before
                 * disconnecting, but that we must also tolerate
                 * guests that don't wait for our reply. */
502
                nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, option, NULL);
503
                return 1;
504 505

            case NBD_OPT_EXPORT_NAME:
506
                return nbd_negotiate_handle_export_name(client, length, errp);
507

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

            default:
552 553
                error_setg(errp, "Unsupported option 0x%" PRIx32 " (%s)",
                           option, nbd_opt_lookup(option));
554
                return -EINVAL;
555
            }
556 557 558 559
        }
    }
}

560 561
/* nbd_negotiate
 * Return:
562 563 564 565
 * -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
566
 */
567
static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
B
bellard 已提交
568
{
N
Nick Thomas 已提交
569
    char buf[8 + 8 + 8 + 128];
570
    int ret;
E
Eric Blake 已提交
571
    const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
572 573
                              NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
                              NBD_FLAG_SEND_WRITE_ZEROES);
574
    bool oldStyle;
E
Eric Blake 已提交
575
    size_t len;
N
Nick Thomas 已提交
576

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

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

595
    qio_channel_set_blocking(client->ioc, false, NULL);
596

597
    trace_nbd_negotiate_begin();
598
    memset(buf, 0, sizeof(buf));
N
Nick Thomas 已提交
599
    memcpy(buf, "NBDMAGIC", 8);
600 601 602

    oldStyle = client->exp != NULL && !client->tlscreds;
    if (oldStyle) {
603 604
        trace_nbd_negotiate_old_style(client->exp->size,
                                      client->exp->nbdflags | myflags);
J
John Snow 已提交
605 606 607
        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 已提交
608

609 610
        if (nbd_write(client->ioc, buf, sizeof(buf), errp) < 0) {
            error_prepend(errp, "write failed: ");
611
            return -EINVAL;
612 613
        }
    } else {
614 615 616
        stq_be_p(buf + 8, NBD_OPTS_MAGIC);
        stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES);

617 618
        if (nbd_write(client->ioc, buf, 18, errp) < 0) {
            error_prepend(errp, "write failed: ");
619
            return -EINVAL;
620
        }
621
        ret = nbd_negotiate_options(client, errp);
622
        if (ret != 0) {
623 624 625
            if (ret < 0) {
                error_prepend(errp, "option negotiation failed: ");
            }
626
            return ret;
627 628
        }

629 630
        trace_nbd_negotiate_new_style_size_flags(
            client->exp->size, client->exp->nbdflags | myflags);
J
John Snow 已提交
631 632
        stq_be_p(buf + 18, client->exp->size);
        stw_be_p(buf + 26, client->exp->nbdflags | myflags);
E
Eric Blake 已提交
633
        len = client->no_zeroes ? 10 : sizeof(buf) - 18;
634
        ret = nbd_write(client->ioc, buf + 18, len, errp);
635
        if (ret < 0) {
636
            error_prepend(errp, "write failed: ");
637
            return ret;
638
        }
N
Nick Thomas 已提交
639 640
    }

641
    trace_nbd_negotiate_success();
642 643

    return 0;
B
bellard 已提交
644 645
}

646 647
static int nbd_receive_request(QIOChannel *ioc, NBDRequest *request,
                               Error **errp)
648
{
P
Paolo Bonzini 已提交
649
    uint8_t buf[NBD_REQUEST_SIZE];
N
Nick Thomas 已提交
650
    uint32_t magic;
651
    int ret;
N
Nick Thomas 已提交
652

653
    ret = nbd_read(ioc, buf, sizeof(buf), errp);
654 655 656 657
    if (ret < 0) {
        return ret;
    }

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

667
    magic = ldl_be_p(buf);
668 669
    request->flags  = lduw_be_p(buf + 4);
    request->type   = lduw_be_p(buf + 6);
670 671 672
    request->handle = ldq_be_p(buf + 8);
    request->from   = ldq_be_p(buf + 16);
    request->len    = ldl_be_p(buf + 24);
N
Nick Thomas 已提交
673

674 675
    trace_nbd_receive_request(magic, request->flags, request->type,
                              request->from, request->len);
N
Nick Thomas 已提交
676 677

    if (magic != NBD_REQUEST_MAGIC) {
678
        error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic);
679
        return -EINVAL;
N
Nick Thomas 已提交
680 681
    }
    return 0;
682 683
}

684
static int nbd_send_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
685
{
P
Paolo Bonzini 已提交
686
    uint8_t buf[NBD_REPLY_SIZE];
N
Nick Thomas 已提交
687

688 689
    reply->error = system_errno_to_nbd_errno(reply->error);

690
    trace_nbd_send_reply(reply->error, reply->handle);
691

N
Nick Thomas 已提交
692 693 694 695 696
    /* Reply
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
       [ 4 ..  7]    error   (0 == no error)
       [ 7 .. 15]    handle
     */
J
John Snow 已提交
697 698 699
    stl_be_p(buf, NBD_REPLY_MAGIC);
    stl_be_p(buf + 4, reply->error);
    stq_be_p(buf + 8, reply->handle);
N
Nick Thomas 已提交
700

701
    return nbd_write(ioc, buf, sizeof(buf), errp);
702
}
B
bellard 已提交
703

P
Paolo Bonzini 已提交
704 705
#define MAX_NBD_REQUESTS 16

706
void nbd_client_get(NBDClient *client)
707 708 709 710
{
    client->refcount++;
}

711
void nbd_client_put(NBDClient *client)
712 713
{
    if (--client->refcount == 0) {
714
        /* The last reference should be dropped by client->close,
M
Max Reitz 已提交
715
         * which is called by client_close.
716 717 718
         */
        assert(client->closing);

719
        qio_channel_detach_aio_context(client->ioc);
720 721
        object_unref(OBJECT(client->sioc));
        object_unref(OBJECT(client->ioc));
722 723 724 725
        if (client->tlscreds) {
            object_unref(OBJECT(client->tlscreds));
        }
        g_free(client->tlsaclname);
726 727 728 729
        if (client->exp) {
            QTAILQ_REMOVE(&client->exp->clients, client, next);
            nbd_export_put(client->exp);
        }
730 731 732 733
        g_free(client);
    }
}

734
static void client_close(NBDClient *client, bool negotiated)
735
{
736 737 738 739 740 741 742 743 744
    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.
     */
745 746
    qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH,
                         NULL);
747 748

    /* Also tell the client, so that they release their reference.  */
749 750
    if (client->close_fn) {
        client->close_fn(client, negotiated);
751 752 753
    }
}

754
static NBDRequestData *nbd_request_get(NBDClient *client)
P
Paolo Bonzini 已提交
755
{
756
    NBDRequestData *req;
757

P
Paolo Bonzini 已提交
758 759 760
    assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
    client->nb_requests++;

761
    req = g_new0(NBDRequestData, 1);
762 763
    nbd_client_get(client);
    req->client = client;
P
Paolo Bonzini 已提交
764 765 766
    return req;
}

767
static void nbd_request_put(NBDRequestData *req)
P
Paolo Bonzini 已提交
768
{
769
    NBDClient *client = req->client;
770

771 772 773
    if (req->data) {
        qemu_vfree(req->data);
    }
774
    g_free(req);
775

M
Max Reitz 已提交
776
    client->nb_requests--;
777 778
    nbd_client_receive_next_request(client);

779
    nbd_client_put(client);
P
Paolo Bonzini 已提交
780 781
}

M
Max Reitz 已提交
782
static void blk_aio_attached(AioContext *ctx, void *opaque)
M
Max Reitz 已提交
783 784 785 786
{
    NBDExport *exp = opaque;
    NBDClient *client;

787
    trace_nbd_blk_aio_attached(exp->name, ctx);
M
Max Reitz 已提交
788 789 790 791

    exp->ctx = ctx;

    QTAILQ_FOREACH(client, &exp->clients, next) {
792 793 794 795 796 797 798
        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 已提交
799 800 801
    }
}

M
Max Reitz 已提交
802
static void blk_aio_detach(void *opaque)
M
Max Reitz 已提交
803 804 805 806
{
    NBDExport *exp = opaque;
    NBDClient *client;

807
    trace_nbd_blk_aio_detach(exp->name, exp->ctx);
M
Max Reitz 已提交
808 809

    QTAILQ_FOREACH(client, &exp->clients, next) {
810
        qio_channel_detach_aio_context(client->ioc);
M
Max Reitz 已提交
811 812 813 814 815
    }

    exp->ctx = NULL;
}

816 817 818 819 820 821
static void nbd_eject_notifier(Notifier *n, void *data)
{
    NBDExport *exp = container_of(n, NBDExport, eject_notifier);
    nbd_export_close(exp);
}

822
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
E
Eric Blake 已提交
823
                          uint16_t nbdflags, void (*close)(NBDExport *),
824
                          bool writethrough, BlockBackend *on_eject_blk,
M
Max Reitz 已提交
825
                          Error **errp)
P
Paolo Bonzini 已提交
826
{
827
    BlockBackend *blk;
P
Paolo Bonzini 已提交
828
    NBDExport *exp = g_malloc0(sizeof(NBDExport));
829
    uint64_t perm;
830
    int ret;
831

832 833 834 835 836 837 838 839
    /* 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);
840 841 842 843
    ret = blk_insert_bs(blk, bs, errp);
    if (ret < 0) {
        goto fail;
    }
844 845
    blk_set_enable_write_cache(blk, !writethrough);

846
    exp->refcount = 1;
847
    QTAILQ_INIT(&exp->clients);
M
Max Reitz 已提交
848
    exp->blk = blk;
P
Paolo Bonzini 已提交
849 850
    exp->dev_offset = dev_offset;
    exp->nbdflags = nbdflags;
M
Max Reitz 已提交
851 852 853 854 855 856 857 858
    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;

859
    exp->close = close;
M
Max Reitz 已提交
860 861
    exp->ctx = blk_get_aio_context(blk);
    blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
862

863 864 865 866 867 868
    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);
    }
869

870 871
    /*
     * NBD exports are used for non-shared storage migration.  Make sure
872
     * that BDRV_O_INACTIVE is cleared and the image is ready for write
873 874
     * access since the export could be available before migration handover.
     */
875
    aio_context_acquire(exp->ctx);
M
Max Reitz 已提交
876
    blk_invalidate_cache(blk, NULL);
877
    aio_context_release(exp->ctx);
P
Paolo Bonzini 已提交
878
    return exp;
M
Max Reitz 已提交
879 880

fail:
881
    blk_unref(blk);
M
Max Reitz 已提交
882 883
    g_free(exp);
    return NULL;
P
Paolo Bonzini 已提交
884 885
}

P
Paolo Bonzini 已提交
886 887 888 889 890 891 892 893 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
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);
}

919 920 921 922 923 924
void nbd_export_set_description(NBDExport *exp, const char *description)
{
    g_free(exp->description);
    exp->description = g_strdup(description);
}

P
Paolo Bonzini 已提交
925 926
void nbd_export_close(NBDExport *exp)
{
927
    NBDClient *client, *next;
928

929 930
    nbd_export_get(exp);
    QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
931
        client_close(client, true);
932
    }
P
Paolo Bonzini 已提交
933
    nbd_export_set_name(exp, NULL);
934
    nbd_export_set_description(exp, NULL);
935
    nbd_export_put(exp);
936 937 938 939 940 941 942 943 944 945 946 947 948
}

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 已提交
949 950
    }

951
    if (--exp->refcount == 0) {
P
Paolo Bonzini 已提交
952
        assert(exp->name == NULL);
953
        assert(exp->description == NULL);
P
Paolo Bonzini 已提交
954

955 956 957 958
        if (exp->close) {
            exp->close(exp);
        }

959
        if (exp->blk) {
960 961 962 963
            if (exp->eject_notifier_blk) {
                notifier_remove(&exp->eject_notifier);
                blk_unref(exp->eject_notifier_blk);
            }
964 965 966 967 968 969
            blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
                                            blk_aio_detach, exp);
            blk_unref(exp->blk);
            exp->blk = NULL;
        }

970 971
        g_free(exp);
    }
P
Paolo Bonzini 已提交
972 973
}

974
BlockBackend *nbd_export_get_blockdev(NBDExport *exp)
P
Paolo Bonzini 已提交
975
{
M
Max Reitz 已提交
976
    return exp->blk;
P
Paolo Bonzini 已提交
977 978
}

P
Paolo Bonzini 已提交
979 980 981 982 983 984 985 986 987
void nbd_export_close_all(void)
{
    NBDExport *exp, *next;

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

988 989
static int nbd_co_send_reply(NBDRequestData *req, NBDReply *reply, int len,
                             Error **errp)
990
{
991
    NBDClient *client = req->client;
992
    int ret;
993

994
    g_assert(qemu_in_coroutine());
995

996
    trace_nbd_co_send_reply(reply->handle, reply->error, len);
997

P
Paolo Bonzini 已提交
998 999 1000
    qemu_co_mutex_lock(&client->send_lock);
    client->send_coroutine = qemu_coroutine_self();

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

    client->send_coroutine = NULL;
    qemu_co_mutex_unlock(&client->send_lock);
1017
    return ret;
1018 1019
}

1020 1021 1022 1023 1024 1025
/* 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).
 */
1026 1027
static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
                                  Error **errp)
1028
{
1029
    NBDClient *client = req->client;
1030

1031
    g_assert(qemu_in_coroutine());
1032
    assert(client->recv_coroutine == qemu_coroutine_self());
1033
    if (nbd_receive_request(client->ioc, request, errp) < 0) {
1034
        return -EIO;
1035 1036
    }

1037 1038
    trace_nbd_co_receive_request_decode_type(request->handle, request->type,
                                             nbd_cmd_lookup(request->type));
1039

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

1045
    if (request->type == NBD_CMD_DISC) {
1046 1047
        /* Special case: we're going to disconnect without a reply,
         * whether or not flags, from, or len are bogus */
1048
        return -EIO;
1049 1050 1051 1052 1053
    }

    /* 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.  */
1054
    if ((request->from + request->len) < request->from) {
1055 1056
        error_setg(errp,
                   "integer overflow detected, you're probably being attacked");
1057
        return -EINVAL;
1058 1059
    }

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

1067 1068
        req->data = blk_try_blockalign(client->exp->blk, request->len);
        if (req->data == NULL) {
1069
            error_setg(errp, "No memory");
1070
            return -ENOMEM;
1071
        }
1072
    }
1073
    if (request->type == NBD_CMD_WRITE) {
1074 1075
        if (nbd_read(client->ioc, req->data, request->len, errp) < 0) {
            error_prepend(errp, "reading from socket failed: ");
1076
            return -EIO;
1077
        }
1078
        req->complete = true;
1079

1080 1081
        trace_nbd_co_receive_request_payload_received(request->handle,
                                                      request->len);
1082
    }
1083 1084 1085

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

1101
    return 0;
1102 1103
}

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

1117
    trace_nbd_trip();
1118
    if (client->closing) {
1119
        nbd_client_put(client);
1120 1121
        return;
    }
N
Nick Thomas 已提交
1122

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

1131 1132 1133
    reply.handle = request.handle;
    reply.error = 0;

1134 1135
    if (ret < 0) {
        reply.error = -ret;
1136
        goto reply;
N
Nick Thomas 已提交
1137 1138
    }

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

1147
    switch (request.type) {
N
Nick Thomas 已提交
1148
    case NBD_CMD_READ:
1149 1150
        /* XXX: NBD Protocol only documents use of FUA with WRITE */
        if (request.flags & NBD_CMD_FLAG_FUA) {
M
Max Reitz 已提交
1151
            ret = blk_co_flush(exp->blk);
P
Paolo Bonzini 已提交
1152
            if (ret < 0) {
1153
                error_setg_errno(&local_err, -ret, "flush failed");
P
Paolo Bonzini 已提交
1154
                reply.error = -ret;
1155
                break;
P
Paolo Bonzini 已提交
1156 1157 1158
            }
        }

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

1167 1168
        reply_data_len = request.len;

N
Nick Thomas 已提交
1169 1170
        break;
    case NBD_CMD_WRITE:
P
Paolo Bonzini 已提交
1171
        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
1172
            reply.error = EROFS;
1173
            break;
1174 1175
        }

1176
        flags = 0;
1177
        if (request.flags & NBD_CMD_FLAG_FUA) {
1178 1179
            flags |= BDRV_REQ_FUA;
        }
1180
        ret = blk_pwrite(exp->blk, request.from + exp->dev_offset,
1181
                         req->data, request.len, flags);
1182
        if (ret < 0) {
1183
            error_setg_errno(&local_err, -ret, "writing to file failed");
1184 1185
            reply.error = -ret;
        }
N
Nick Thomas 已提交
1186

1187 1188 1189
        break;
    case NBD_CMD_WRITE_ZEROES:
        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
1190
            error_setg(&local_err, "Server is read-only, return error");
1191
            reply.error = EROFS;
1192
            break;
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
        }

        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) {
1205
            error_setg_errno(&local_err, -ret, "writing to file failed");
1206 1207 1208
            reply.error = -ret;
        }

N
Nick Thomas 已提交
1209 1210
        break;
    case NBD_CMD_DISC:
1211 1212 1213
        /* unreachable, thanks to special case in nbd_co_receive_request() */
        abort();

P
Paolo Bonzini 已提交
1214
    case NBD_CMD_FLUSH:
M
Max Reitz 已提交
1215
        ret = blk_co_flush(exp->blk);
P
Paolo Bonzini 已提交
1216
        if (ret < 0) {
1217
            error_setg_errno(&local_err, -ret, "flush failed");
P
Paolo Bonzini 已提交
1218 1219
            reply.error = -ret;
        }
1220

P
Paolo Bonzini 已提交
1221 1222
        break;
    case NBD_CMD_TRIM:
1223 1224 1225
        ret = blk_co_pdiscard(exp->blk, request.from + exp->dev_offset,
                              request.len);
        if (ret < 0) {
1226
            error_setg_errno(&local_err, -ret, "discard failed");
1227
            reply.error = -ret;
P
Paolo Bonzini 已提交
1228
        }
1229

P
Paolo Bonzini 已提交
1230
        break;
N
Nick Thomas 已提交
1231
    default:
1232 1233
        error_setg(&local_err, "invalid request type (%" PRIu32 ") received",
                   request.type);
Y
Yik Fang 已提交
1234
        reply.error = EINVAL;
1235 1236 1237
    }

reply:
1238 1239 1240 1241 1242 1243 1244
    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;
    }

1245 1246
    if (nbd_co_send_reply(req, &reply, reply_data_len, &local_err) < 0) {
        error_prepend(&local_err, "Failed to send reply: ");
1247 1248 1249
        goto disconnect;
    }

1250 1251 1252
    /* We must disconnect after NBD_CMD_WRITE if we did not
     * read the payload.
     */
1253 1254
    if (!req->complete) {
        error_setg(&local_err, "Request handling failed in intermediate state");
1255
        goto disconnect;
N
Nick Thomas 已提交
1256 1257
    }

1258
done:
P
Paolo Bonzini 已提交
1259
    nbd_request_put(req);
1260
    nbd_client_put(client);
P
Paolo Bonzini 已提交
1261 1262
    return;

1263
disconnect:
1264 1265 1266
    if (local_err) {
        error_reportf_err(local_err, "Disconnect client, due to: ");
    }
1267
    nbd_request_put(req);
1268
    client_close(client, true);
1269
    nbd_client_put(client);
B
bellard 已提交
1270
}
P
Paolo Bonzini 已提交
1271

1272
static void nbd_client_receive_next_request(NBDClient *client)
M
Max Reitz 已提交
1273
{
1274 1275 1276 1277
    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 已提交
1278 1279 1280
    }
}

1281 1282
static coroutine_fn void nbd_co_client_start(void *opaque)
{
1283
    NBDClient *client = opaque;
1284
    NBDExport *exp = client->exp;
1285
    Error *local_err = NULL;
1286 1287 1288

    if (exp) {
        nbd_export_get(exp);
1289
        QTAILQ_INSERT_TAIL(&exp->clients, client, next);
1290
    }
1291 1292
    qemu_co_mutex_init(&client->send_lock);

1293 1294 1295 1296
    if (nbd_negotiate(client, &local_err)) {
        if (local_err) {
            error_report_err(local_err);
        }
1297
        client_close(client, false);
1298
        return;
1299
    }
1300 1301

    nbd_client_receive_next_request(client);
1302 1303
}

1304 1305 1306 1307 1308 1309
/*
 * 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.
 */
1310 1311
void nbd_client_new(NBDExport *exp,
                    QIOChannelSocket *sioc,
1312 1313
                    QCryptoTLSCreds *tlscreds,
                    const char *tlsaclname,
1314
                    void (*close_fn)(NBDClient *, bool))
P
Paolo Bonzini 已提交
1315
{
1316
    NBDClient *client;
1317
    Coroutine *co;
1318

1319 1320 1321
    client = g_malloc0(sizeof(NBDClient));
    client->refcount = 1;
    client->exp = exp;
1322 1323 1324 1325 1326
    client->tlscreds = tlscreds;
    if (tlscreds) {
        object_ref(OBJECT(client->tlscreds));
    }
    client->tlsaclname = g_strdup(tlsaclname);
1327 1328 1329 1330
    client->sioc = sioc;
    object_ref(OBJECT(client->sioc));
    client->ioc = QIO_CHANNEL(sioc);
    object_ref(OBJECT(client->ioc));
1331
    client->close_fn = close_fn;
1332

1333 1334
    co = qemu_coroutine_create(nbd_co_client_start, client);
    qemu_coroutine_enter(co);
P
Paolo Bonzini 已提交
1335
}