server.c 36.1 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 42 43 44 45 46 47
        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;
    case EINVAL:
    default:
        return NBD_EINVAL;
    }
}

48 49 50 51 52 53 54 55
/* Definitions for opaque data types */

typedef struct NBDRequest NBDRequest;

struct NBDRequest {
    QSIMPLEQ_ENTRY(NBDRequest) entry;
    NBDClient *client;
    uint8_t *data;
56
    bool complete;
57 58 59
};

struct NBDExport {
60
    int refcount;
61 62
    void (*close)(NBDExport *exp);

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

    AioContext *ctx;
73

74
    BlockBackend *eject_notifier_blk;
75
    Notifier eject_notifier;
76 77
};

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

80 81 82 83 84
struct NBDClient {
    int refcount;
    void (*close)(NBDClient *client);

    NBDExport *exp;
85 86
    QCryptoTLSCreds *tlscreds;
    char *tlsaclname;
87 88
    QIOChannelSocket *sioc; /* The underlying data channel */
    QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
89 90 91 92 93 94

    Coroutine *recv_coroutine;

    CoMutex send_lock;
    Coroutine *send_coroutine;

M
Max Reitz 已提交
95 96
    bool can_read;

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

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

M
Max Reitz 已提交
104 105 106 107
static void nbd_set_handlers(NBDClient *client);
static void nbd_unset_handlers(NBDClient *client);
static void nbd_update_can_read(NBDClient *client);

108 109 110
static gboolean nbd_negotiate_continue(QIOChannel *ioc,
                                       GIOCondition condition,
                                       void *opaque)
111
{
112
    qemu_coroutine_enter(opaque);
113
    return TRUE;
114 115
}

116
static ssize_t nbd_negotiate_read(QIOChannel *ioc, void *buffer, size_t size)
117 118
{
    ssize_t ret;
119
    guint watch;
120 121 122

    assert(qemu_in_coroutine());
    /* Negotiation are always in main loop. */
123 124 125 126 127 128 129
    watch = qio_channel_add_watch(ioc,
                                  G_IO_IN,
                                  nbd_negotiate_continue,
                                  qemu_coroutine_self(),
                                  NULL);
    ret = read_sync(ioc, buffer, size);
    g_source_remove(watch);
130 131 132 133
    return ret;

}

134 135
static ssize_t nbd_negotiate_write(QIOChannel *ioc, const void *buffer,
                                   size_t size)
136 137
{
    ssize_t ret;
138
    guint watch;
139 140 141

    assert(qemu_in_coroutine());
    /* Negotiation are always in main loop. */
142 143 144 145 146 147 148
    watch = qio_channel_add_watch(ioc,
                                  G_IO_OUT,
                                  nbd_negotiate_continue,
                                  qemu_coroutine_self(),
                                  NULL);
    ret = write_sync(ioc, buffer, size);
    g_source_remove(watch);
149 150 151
    return ret;
}

152
static ssize_t nbd_negotiate_drop_sync(QIOChannel *ioc, size_t size)
153 154 155 156 157
{
    ssize_t ret, dropped = size;
    uint8_t *buffer = g_malloc(MIN(65536, size));

    while (size > 0) {
158
        ret = nbd_negotiate_read(ioc, buffer, MIN(65536, size));
159 160 161 162 163 164 165 166 167 168 169 170 171
        if (ret < 0) {
            g_free(buffer);
            return ret;
        }

        assert(ret <= size);
        size -= ret;
    }

    g_free(buffer);
    return dropped;
}

172
/* Basic flow for negotiation
B
bellard 已提交
173 174 175

   Server         Client
   Negotiate
176 177 178 179 180 181 182 183 184 185 186 187 188

   or

   Server         Client
   Negotiate #1
                  Option
   Negotiate #2

   ----

   followed by

   Server         Client
B
bellard 已提交
189 190 191 192 193 194 195
                  Request
   Response
                  Request
   Response
                  ...
   ...
                  Request (type == 2)
196

B
bellard 已提交
197 198
*/

199
static int nbd_negotiate_send_rep(QIOChannel *ioc, uint32_t type, uint32_t opt)
200 201
{
    uint64_t magic;
202
    uint32_t len;
203

204
    TRACE("Reply opt=%" PRIx32 " type=%" PRIx32, type, opt);
205

206
    magic = cpu_to_be64(NBD_REP_MAGIC);
207
    if (nbd_negotiate_write(ioc, &magic, sizeof(magic)) != sizeof(magic)) {
208 209
        LOG("write failed (rep magic)");
        return -EINVAL;
210
    }
211
    opt = cpu_to_be32(opt);
212
    if (nbd_negotiate_write(ioc, &opt, sizeof(opt)) != sizeof(opt)) {
213 214
        LOG("write failed (rep opt)");
        return -EINVAL;
215
    }
216
    type = cpu_to_be32(type);
217
    if (nbd_negotiate_write(ioc, &type, sizeof(type)) != sizeof(type)) {
218 219
        LOG("write failed (rep type)");
        return -EINVAL;
220
    }
221
    len = cpu_to_be32(0);
222
    if (nbd_negotiate_write(ioc, &len, sizeof(len)) != sizeof(len)) {
223 224
        LOG("write failed (rep data length)");
        return -EINVAL;
225
    }
226 227
    return 0;
}
228

229
static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp)
230
{
231 232
    uint64_t magic;
    size_t name_len, desc_len;
233
    uint32_t opt, type, len;
234 235
    const char *name = exp->name ? exp->name : "";
    const char *desc = exp->description ? exp->description : "";
236

237 238 239
    TRACE("Advertising export name '%s' description '%s'", name, desc);
    name_len = strlen(name);
    desc_len = strlen(desc);
240
    magic = cpu_to_be64(NBD_REP_MAGIC);
241
    if (nbd_negotiate_write(ioc, &magic, sizeof(magic)) != sizeof(magic)) {
242 243 244 245
        LOG("write failed (magic)");
        return -EINVAL;
     }
    opt = cpu_to_be32(NBD_OPT_LIST);
246
    if (nbd_negotiate_write(ioc, &opt, sizeof(opt)) != sizeof(opt)) {
247 248 249 250
        LOG("write failed (opt)");
        return -EINVAL;
    }
    type = cpu_to_be32(NBD_REP_SERVER);
251
    if (nbd_negotiate_write(ioc, &type, sizeof(type)) != sizeof(type)) {
252 253 254
        LOG("write failed (reply type)");
        return -EINVAL;
    }
255
    len = cpu_to_be32(name_len + desc_len + sizeof(len));
256
    if (nbd_negotiate_write(ioc, &len, sizeof(len)) != sizeof(len)) {
257 258 259 260
        LOG("write failed (length)");
        return -EINVAL;
    }
    len = cpu_to_be32(name_len);
261
    if (nbd_negotiate_write(ioc, &len, sizeof(len)) != sizeof(len)) {
262 263 264 265 266
        LOG("write failed (name length)");
        return -EINVAL;
    }
    if (nbd_negotiate_write(ioc, name, name_len) != name_len) {
        LOG("write failed (name buffer)");
267 268
        return -EINVAL;
    }
269 270
    if (nbd_negotiate_write(ioc, desc, desc_len) != desc_len) {
        LOG("write failed (description buffer)");
271 272 273 274 275
        return -EINVAL;
    }
    return 0;
}

276
static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length)
277 278 279 280
{
    NBDExport *exp;

    if (length) {
281
        if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
282 283
            return -EIO;
        }
284 285
        return nbd_negotiate_send_rep(client->ioc,
                                      NBD_REP_ERR_INVALID, NBD_OPT_LIST);
286 287 288 289
    }

    /* For each export, send a NBD_REP_SERVER reply. */
    QTAILQ_FOREACH(exp, &exports, next) {
290
        if (nbd_negotiate_send_rep_list(client->ioc, exp)) {
291 292 293 294
            return -EINVAL;
        }
    }
    /* Finish with a NBD_REP_ACK. */
295
    return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, NBD_OPT_LIST);
296 297
}

298
static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length)
299
{
300
    int rc = -EINVAL;
301
    char name[NBD_MAX_NAME_SIZE + 1];
302

303 304 305
    /* Client sends:
        [20 ..  xx]   export name (length bytes)
     */
306
    TRACE("Checking length");
307
    if (length >= sizeof(name)) {
308 309 310
        LOG("Bad length received");
        goto fail;
    }
311
    if (nbd_negotiate_read(client->ioc, name, length) != length) {
312 313 314 315 316
        LOG("read failed");
        goto fail;
    }
    name[length] = '\0';

317 318
    TRACE("Client requested export '%s'", name);

319 320 321 322 323 324 325 326 327 328 329 330 331
    client->exp = nbd_export_find(name);
    if (!client->exp) {
        LOG("export not found");
        goto fail;
    }

    QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
    nbd_export_get(client->exp);
    rc = 0;
fail:
    return rc;
}

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349

static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
                                                 uint32_t length)
{
    QIOChannel *ioc;
    QIOChannelTLS *tioc;
    struct NBDTLSHandshakeData data = { 0 };

    TRACE("Setting up TLS");
    ioc = client->ioc;
    if (length) {
        if (nbd_negotiate_drop_sync(ioc, length) != length) {
            return NULL;
        }
        nbd_negotiate_send_rep(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS);
        return NULL;
    }

350 351 352 353
    if (nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK,
                               NBD_OPT_STARTTLS) < 0) {
        return NULL;
    }
354 355 356 357 358 359 360 361 362

    tioc = qio_channel_tls_new_server(ioc,
                                      client->tlscreds,
                                      client->tlsaclname,
                                      NULL);
    if (!tioc) {
        return NULL;
    }

363
    qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
    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));
        error_free(data.error);
        return NULL;
    }

    return QIO_CHANNEL(tioc);
}


385
static int nbd_negotiate_options(NBDClient *client)
386
{
M
Max Reitz 已提交
387
    uint32_t flags;
388
    bool fixedNewstyle = false;
M
Max Reitz 已提交
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403

    /* 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
    */

404 405
    if (nbd_negotiate_read(client->ioc, &flags, sizeof(flags)) !=
        sizeof(flags)) {
M
Max Reitz 已提交
406 407 408 409 410
        LOG("read failed");
        return -EIO;
    }
    TRACE("Checking client flags");
    be32_to_cpus(&flags);
411
    if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
412
        TRACE("Client supports fixed newstyle handshake");
413 414 415 416
        fixedNewstyle = true;
        flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
    }
    if (flags != 0) {
417
        TRACE("Unknown client flags 0x%" PRIx32 " received", flags);
M
Max Reitz 已提交
418 419 420
        return -EIO;
    }

421
    while (1) {
M
Max Reitz 已提交
422
        int ret;
423
        uint32_t clientflags, length;
424 425
        uint64_t magic;

426 427
        if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) !=
            sizeof(magic)) {
428 429 430 431 432 433 434 435 436
            LOG("read failed");
            return -EINVAL;
        }
        TRACE("Checking opts magic");
        if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {
            LOG("Bad magic received");
            return -EINVAL;
        }

437 438
        if (nbd_negotiate_read(client->ioc, &clientflags,
                               sizeof(clientflags)) != sizeof(clientflags)) {
439 440 441
            LOG("read failed");
            return -EINVAL;
        }
442
        clientflags = be32_to_cpu(clientflags);
443

444 445
        if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) !=
            sizeof(length)) {
446 447 448 449 450
            LOG("read failed");
            return -EINVAL;
        }
        length = be32_to_cpu(length);

451
        TRACE("Checking option 0x%" PRIx32, clientflags);
452 453 454 455
        if (client->tlscreds &&
            client->ioc == (QIOChannel *)client->sioc) {
            QIOChannel *tioc;
            if (!fixedNewstyle) {
456
                TRACE("Unsupported option 0x%" PRIx32, clientflags);
457 458 459 460 461 462 463 464 465 466 467 468
                return -EINVAL;
            }
            switch (clientflags) {
            case NBD_OPT_STARTTLS:
                tioc = nbd_negotiate_handle_starttls(client, length);
                if (!tioc) {
                    return -EIO;
                }
                object_unref(OBJECT(client->ioc));
                client->ioc = QIO_CHANNEL(tioc);
                break;

469 470 471 472 473
            case NBD_OPT_EXPORT_NAME:
                /* No way to return an error to client, so drop connection */
                TRACE("Option 0x%x not permitted before TLS", clientflags);
                return -EINVAL;

474
            default:
475 476
                TRACE("Option 0x%" PRIx32 " not permitted before TLS",
                      clientflags);
477 478 479
                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
                    return -EIO;
                }
480 481 482 483 484
                ret = nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_TLS_REQD,
                                             clientflags);
                if (ret < 0) {
                    return ret;
                }
485
                break;
486 487
            }
        } else if (fixedNewstyle) {
488 489 490 491 492 493 494 495 496 497 498 499 500 501
            switch (clientflags) {
            case NBD_OPT_LIST:
                ret = nbd_negotiate_handle_list(client, length);
                if (ret < 0) {
                    return ret;
                }
                break;

            case NBD_OPT_ABORT:
                return -EINVAL;

            case NBD_OPT_EXPORT_NAME:
                return nbd_negotiate_handle_export_name(client, length);

502
            case NBD_OPT_STARTTLS:
503 504 505
                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
                    return -EIO;
                }
506 507
                if (client->tlscreds) {
                    TRACE("TLS already enabled");
508 509 510
                    ret = nbd_negotiate_send_rep(client->ioc,
                                                 NBD_REP_ERR_INVALID,
                                                 clientflags);
511 512
                } else {
                    TRACE("TLS not configured");
513 514 515 516 517 518
                    ret = nbd_negotiate_send_rep(client->ioc,
                                                 NBD_REP_ERR_POLICY,
                                                 clientflags);
                }
                if (ret < 0) {
                    return ret;
519
                }
520
                break;
521
            default:
522
                TRACE("Unsupported option 0x%" PRIx32, clientflags);
523 524 525
                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
                    return -EIO;
                }
526 527 528 529 530
                ret = nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP,
                                             clientflags);
                if (ret < 0) {
                    return ret;
                }
531
                break;
532 533 534 535 536 537 538 539 540 541 542
            }
        } else {
            /*
             * If broken new-style we should drop the connection
             * for anything except NBD_OPT_EXPORT_NAME
             */
            switch (clientflags) {
            case NBD_OPT_EXPORT_NAME:
                return nbd_negotiate_handle_export_name(client, length);

            default:
543
                TRACE("Unsupported option 0x%" PRIx32, clientflags);
544
                return -EINVAL;
545
            }
546 547 548 549
        }
    }
}

550 551 552 553 554 555
typedef struct {
    NBDClient *client;
    Coroutine *co;
} NBDClientNewData;

static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
B
bellard 已提交
556
{
557
    NBDClient *client = data->client;
N
Nick Thomas 已提交
558
    char buf[8 + 8 + 8 + 128];
559
    int rc;
E
Eric Blake 已提交
560 561
    const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
                              NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
562
    bool oldStyle;
N
Nick Thomas 已提交
563

564
    /* Old style negotiation header without options
565 566
        [ 0 ..   7]   passwd       ("NBDMAGIC")
        [ 8 ..  15]   magic        (NBD_CLIENT_MAGIC)
N
Nick Thomas 已提交
567
        [16 ..  23]   size
568
        [24 ..  25]   server flags (0)
H
Hani Benhabiles 已提交
569
        [26 ..  27]   export flags
570 571
        [28 .. 151]   reserved     (0)

572
       New style negotiation header with options
573 574 575
        [ 0 ..   7]   passwd       ("NBDMAGIC")
        [ 8 ..  15]   magic        (NBD_OPTS_MAGIC)
        [16 ..  17]   server flags (0)
576
        ....options sent....
577 578 579
        [18 ..  25]   size
        [26 ..  27]   export flags
        [28 .. 151]   reserved     (0)
N
Nick Thomas 已提交
580 581
     */

582
    qio_channel_set_blocking(client->ioc, false, NULL);
583 584
    rc = -EINVAL;

N
Nick Thomas 已提交
585
    TRACE("Beginning negotiation.");
586
    memset(buf, 0, sizeof(buf));
N
Nick Thomas 已提交
587
    memcpy(buf, "NBDMAGIC", 8);
588 589 590

    oldStyle = client->exp != NULL && !client->tlscreds;
    if (oldStyle) {
591 592
        TRACE("advertising size %" PRIu64 " and flags %x",
              client->exp->size, client->exp->nbdflags | myflags);
J
John Snow 已提交
593 594 595
        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);
596
    } else {
J
John Snow 已提交
597 598
        stq_be_p(buf + 8, NBD_OPTS_MAGIC);
        stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE);
599
    }
N
Nick Thomas 已提交
600

601 602 603 604 605
    if (oldStyle) {
        if (client->tlscreds) {
            TRACE("TLS cannot be enabled with oldstyle protocol");
            goto fail;
        }
606
        if (nbd_negotiate_write(client->ioc, buf, sizeof(buf)) != sizeof(buf)) {
607 608 609 610
            LOG("write failed");
            goto fail;
        }
    } else {
611
        if (nbd_negotiate_write(client->ioc, buf, 18) != 18) {
612 613 614
            LOG("write failed");
            goto fail;
        }
615
        rc = nbd_negotiate_options(client);
616
        if (rc != 0) {
617 618 619 620
            LOG("option negotiation failed");
            goto fail;
        }

621 622
        TRACE("advertising size %" PRIu64 " and flags %x",
              client->exp->size, client->exp->nbdflags | myflags);
J
John Snow 已提交
623 624
        stq_be_p(buf + 18, client->exp->size);
        stw_be_p(buf + 26, client->exp->nbdflags | myflags);
625 626
        if (nbd_negotiate_write(client->ioc, buf + 18, sizeof(buf) - 18) !=
            sizeof(buf) - 18) {
627 628 629
            LOG("write failed");
            goto fail;
        }
N
Nick Thomas 已提交
630 631
    }

D
Dong Xu Wang 已提交
632
    TRACE("Negotiation succeeded.");
633 634 635
    rc = 0;
fail:
    return rc;
B
bellard 已提交
636 637
}

638
static ssize_t nbd_receive_request(QIOChannel *ioc, struct nbd_request *request)
639
{
P
Paolo Bonzini 已提交
640
    uint8_t buf[NBD_REQUEST_SIZE];
N
Nick Thomas 已提交
641
    uint32_t magic;
642
    ssize_t ret;
N
Nick Thomas 已提交
643

644
    ret = read_sync(ioc, buf, sizeof(buf));
645 646 647 648 649
    if (ret < 0) {
        return ret;
    }

    if (ret != sizeof(buf)) {
N
Nick Thomas 已提交
650
        LOG("read failed");
651
        return -EINVAL;
N
Nick Thomas 已提交
652 653 654 655
    }

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

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

670 671 672
    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 已提交
673 674

    if (magic != NBD_REQUEST_MAGIC) {
675
        LOG("invalid magic (got 0x%" PRIx32 ")", magic);
676
        return -EINVAL;
N
Nick Thomas 已提交
677 678
    }
    return 0;
679 680
}

681
static ssize_t nbd_send_reply(QIOChannel *ioc, struct nbd_reply *reply)
682
{
P
Paolo Bonzini 已提交
683
    uint8_t buf[NBD_REPLY_SIZE];
684
    ssize_t ret;
N
Nick Thomas 已提交
685

686 687
    reply->error = system_errno_to_nbd_errno(reply->error);

688 689
    TRACE("Sending response to client: { .error = %" PRId32
          ", handle = %" PRIu64 " }",
690 691
          reply->error, reply->handle);

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
    ret = write_sync(ioc, buf, sizeof(buf));
702 703 704 705 706
    if (ret < 0) {
        return ret;
    }

    if (ret != sizeof(buf)) {
N
Nick Thomas 已提交
707
        LOG("writing to socket failed");
708
        return -EINVAL;
N
Nick Thomas 已提交
709 710
    }
    return 0;
711
}
B
bellard 已提交
712

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

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

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

M
Max Reitz 已提交
728
        nbd_unset_handlers(client);
729 730
        object_unref(OBJECT(client->sioc));
        object_unref(OBJECT(client->ioc));
731 732 733 734
        if (client->tlscreds) {
            object_unref(OBJECT(client->tlscreds));
        }
        g_free(client->tlsaclname);
735 736 737 738
        if (client->exp) {
            QTAILQ_REMOVE(&client->exp->clients, client, next);
            nbd_export_put(client->exp);
        }
739 740 741 742
        g_free(client);
    }
}

M
Max Reitz 已提交
743
static void client_close(NBDClient *client)
744
{
745 746 747 748 749 750 751 752 753
    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.
     */
754 755
    qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH,
                         NULL);
756 757

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

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

P
Paolo Bonzini 已提交
767 768
    assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
    client->nb_requests++;
M
Max Reitz 已提交
769
    nbd_update_can_read(client);
P
Paolo Bonzini 已提交
770

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

777
static void nbd_request_put(NBDRequest *req)
P
Paolo Bonzini 已提交
778
{
779
    NBDClient *client = req->client;
780

781 782 783
    if (req->data) {
        qemu_vfree(req->data);
    }
784
    g_free(req);
785

M
Max Reitz 已提交
786 787
    client->nb_requests--;
    nbd_update_can_read(client);
788
    nbd_client_put(client);
P
Paolo Bonzini 已提交
789 790
}

M
Max Reitz 已提交
791
static void blk_aio_attached(AioContext *ctx, void *opaque)
M
Max Reitz 已提交
792 793 794 795 796 797 798 799 800 801 802 803 804
{
    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) {
        nbd_set_handlers(client);
    }
}

M
Max Reitz 已提交
805
static void blk_aio_detach(void *opaque)
M
Max Reitz 已提交
806 807 808 809 810 811 812 813 814 815 816 817 818
{
    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) {
        nbd_unset_handlers(client);
    }

    exp->ctx = NULL;
}

819 820 821 822 823 824
static void nbd_eject_notifier(Notifier *n, void *data)
{
    NBDExport *exp = container_of(n, NBDExport, eject_notifier);
    nbd_export_close(exp);
}

825
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
E
Eric Blake 已提交
826
                          uint16_t nbdflags, void (*close)(NBDExport *),
827
                          bool writethrough, BlockBackend *on_eject_blk,
M
Max Reitz 已提交
828
                          Error **errp)
P
Paolo Bonzini 已提交
829
{
830
    BlockBackend *blk;
P
Paolo Bonzini 已提交
831
    NBDExport *exp = g_malloc0(sizeof(NBDExport));
832 833 834 835 836

    blk = blk_new();
    blk_insert_bs(blk, bs);
    blk_set_enable_write_cache(blk, !writethrough);

837
    exp->refcount = 1;
838
    QTAILQ_INIT(&exp->clients);
M
Max Reitz 已提交
839
    exp->blk = blk;
P
Paolo Bonzini 已提交
840 841
    exp->dev_offset = dev_offset;
    exp->nbdflags = nbdflags;
M
Max Reitz 已提交
842 843 844 845 846 847 848 849
    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;

850
    exp->close = close;
M
Max Reitz 已提交
851 852
    exp->ctx = blk_get_aio_context(blk);
    blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
853

854 855 856 857 858 859
    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);
    }
860

861 862
    /*
     * NBD exports are used for non-shared storage migration.  Make sure
863
     * that BDRV_O_INACTIVE is cleared and the image is ready for write
864 865
     * access since the export could be available before migration handover.
     */
866
    aio_context_acquire(exp->ctx);
M
Max Reitz 已提交
867
    blk_invalidate_cache(blk, NULL);
868
    aio_context_release(exp->ctx);
P
Paolo Bonzini 已提交
869
    return exp;
M
Max Reitz 已提交
870 871

fail:
872
    blk_unref(blk);
M
Max Reitz 已提交
873 874
    g_free(exp);
    return NULL;
P
Paolo Bonzini 已提交
875 876
}

P
Paolo Bonzini 已提交
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
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);
}

910 911 912 913 914 915
void nbd_export_set_description(NBDExport *exp, const char *description)
{
    g_free(exp->description);
    exp->description = g_strdup(description);
}

P
Paolo Bonzini 已提交
916 917
void nbd_export_close(NBDExport *exp)
{
918
    NBDClient *client, *next;
919

920 921
    nbd_export_get(exp);
    QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
M
Max Reitz 已提交
922
        client_close(client);
923
    }
P
Paolo Bonzini 已提交
924
    nbd_export_set_name(exp, NULL);
925
    nbd_export_set_description(exp, NULL);
926
    nbd_export_put(exp);
927 928 929 930 931 932 933 934 935 936 937 938 939
}

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 已提交
940 941
    }

942
    if (--exp->refcount == 0) {
P
Paolo Bonzini 已提交
943
        assert(exp->name == NULL);
944
        assert(exp->description == NULL);
P
Paolo Bonzini 已提交
945

946 947 948 949
        if (exp->close) {
            exp->close(exp);
        }

950
        if (exp->blk) {
951 952 953 954
            if (exp->eject_notifier_blk) {
                notifier_remove(&exp->eject_notifier);
                blk_unref(exp->eject_notifier_blk);
            }
955 956 957 958 959 960
            blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
                                            blk_aio_detach, exp);
            blk_unref(exp->blk);
            exp->blk = NULL;
        }

961 962
        g_free(exp);
    }
P
Paolo Bonzini 已提交
963 964
}

965
BlockBackend *nbd_export_get_blockdev(NBDExport *exp)
P
Paolo Bonzini 已提交
966
{
M
Max Reitz 已提交
967
    return exp->blk;
P
Paolo Bonzini 已提交
968 969
}

P
Paolo Bonzini 已提交
970 971 972 973 974 975 976 977 978
void nbd_export_close_all(void)
{
    NBDExport *exp, *next;

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

P
Paolo Bonzini 已提交
979 980
static ssize_t nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply,
                                 int len)
981
{
982
    NBDClient *client = req->client;
P
Paolo Bonzini 已提交
983
    ssize_t rc, ret;
984

985
    g_assert(qemu_in_coroutine());
P
Paolo Bonzini 已提交
986 987
    qemu_co_mutex_lock(&client->send_lock);
    client->send_coroutine = qemu_coroutine_self();
M
Max Reitz 已提交
988
    nbd_set_handlers(client);
P
Paolo Bonzini 已提交
989

990
    if (!len) {
991
        rc = nbd_send_reply(client->ioc, reply);
992
    } else {
993 994
        qio_channel_set_cork(client->ioc, true);
        rc = nbd_send_reply(client->ioc, reply);
995
        if (rc >= 0) {
996
            ret = write_sync(client->ioc, req->data, len);
997
            if (ret != len) {
998
                rc = -EIO;
999 1000
            }
        }
1001
        qio_channel_set_cork(client->ioc, false);
1002
    }
P
Paolo Bonzini 已提交
1003 1004

    client->send_coroutine = NULL;
M
Max Reitz 已提交
1005
    nbd_set_handlers(client);
P
Paolo Bonzini 已提交
1006
    qemu_co_mutex_unlock(&client->send_lock);
1007 1008 1009
    return rc;
}

1010 1011 1012 1013 1014 1015 1016
/* Collect a client request.  Return 0 if request looks valid, -EAGAIN
 * to keep trying the collection, -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).  */
static ssize_t nbd_co_receive_request(NBDRequest *req,
                                      struct nbd_request *request)
1017
{
1018
    NBDClient *client = req->client;
P
Paolo Bonzini 已提交
1019
    ssize_t rc;
1020

1021
    g_assert(qemu_in_coroutine());
P
Paolo Bonzini 已提交
1022
    client->recv_coroutine = qemu_coroutine_self();
M
Max Reitz 已提交
1023 1024
    nbd_update_can_read(client);

1025
    rc = nbd_receive_request(client->ioc, request);
1026 1027 1028 1029
    if (rc < 0) {
        if (rc != -EAGAIN) {
            rc = -EIO;
        }
1030 1031 1032
        goto out;
    }

1033 1034
    TRACE("Decoding type");

1035
    if (request->type != NBD_CMD_WRITE) {
1036 1037 1038 1039
        /* No payload, we are ready to read the next request.  */
        req->complete = true;
    }

1040
    if (request->type == NBD_CMD_DISC) {
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
        /* Special case: we're going to disconnect without a reply,
         * whether or not flags, from, or len are bogus */
        TRACE("Request type is DISCONNECT");
        rc = -EIO;
        goto out;
    }

    /* 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.  */
1051
    if ((request->from + request->len) < request->from) {
1052
        LOG("integer overflow detected, you're probably being attacked");
1053 1054 1055 1056
        rc = -EINVAL;
        goto out;
    }

1057
    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE) {
1058
        if (request->len > NBD_MAX_BUFFER_SIZE) {
1059
            LOG("len (%" PRIu32" ) is larger than max len (%u)",
1060 1061 1062 1063 1064
                request->len, NBD_MAX_BUFFER_SIZE);
            rc = -EINVAL;
            goto out;
        }

1065 1066 1067 1068 1069
        req->data = blk_try_blockalign(client->exp->blk, request->len);
        if (req->data == NULL) {
            rc = -ENOMEM;
            goto out;
        }
1070
    }
1071
    if (request->type == NBD_CMD_WRITE) {
1072
        TRACE("Reading %" PRIu32 " byte(s)", request->len);
1073

1074
        if (read_sync(client->ioc, req->data, request->len) != request->len) {
1075 1076 1077 1078
            LOG("reading from socket failed");
            rc = -EIO;
            goto out;
        }
1079
        req->complete = true;
1080
    }
1081 1082 1083 1084 1085 1086

    /* Sanity checks, part 2. */
    if (request->from + request->len > client->exp->size) {
        LOG("operation past EOF; From: %" PRIu64 ", Len: %" PRIu32
            ", Size: %" PRIu64, request->from, request->len,
            (uint64_t)client->exp->size);
1087
        rc = request->type == NBD_CMD_WRITE ? -ENOSPC : -EINVAL;
1088 1089
        goto out;
    }
1090 1091
    if (request->flags & ~NBD_CMD_FLAG_FUA) {
        LOG("unsupported flags (got 0x%x)", request->flags);
1092 1093
        rc = -EINVAL;
        goto out;
E
Eric Blake 已提交
1094
    }
1095

1096 1097 1098
    rc = 0;

out:
P
Paolo Bonzini 已提交
1099
    client->recv_coroutine = NULL;
M
Max Reitz 已提交
1100 1101
    nbd_update_can_read(client);

1102 1103 1104
    return rc;
}

P
Paolo Bonzini 已提交
1105
static void nbd_trip(void *opaque)
1106
{
P
Paolo Bonzini 已提交
1107
    NBDClient *client = opaque;
1108
    NBDExport *exp = client->exp;
1109
    NBDRequest *req;
N
Nick Thomas 已提交
1110 1111
    struct nbd_request request;
    struct nbd_reply reply;
P
Paolo Bonzini 已提交
1112
    ssize_t ret;
1113
    int flags;
N
Nick Thomas 已提交
1114 1115

    TRACE("Reading request.");
1116 1117 1118
    if (client->closing) {
        return;
    }
N
Nick Thomas 已提交
1119

1120
    req = nbd_request_get(client);
P
Paolo Bonzini 已提交
1121
    ret = nbd_co_receive_request(req, &request);
1122 1123 1124
    if (ret == -EAGAIN) {
        goto done;
    }
1125
    if (ret == -EIO) {
P
Paolo Bonzini 已提交
1126
        goto out;
1127
    }
N
Nick Thomas 已提交
1128

1129 1130 1131
    reply.handle = request.handle;
    reply.error = 0;

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

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

1145
    switch (request.type) {
N
Nick Thomas 已提交
1146 1147 1148
    case NBD_CMD_READ:
        TRACE("Request type is 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 1153 1154 1155 1156 1157 1158
            if (ret < 0) {
                LOG("flush failed");
                reply.error = -ret;
                goto error_reply;
            }
        }

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

1167
        TRACE("Read %" PRIu32" byte(s)", request.len);
P
Paolo Bonzini 已提交
1168
        if (nbd_co_send_reply(req, &reply, request.len) < 0)
P
Paolo Bonzini 已提交
1169
            goto out;
N
Nick Thomas 已提交
1170 1171 1172 1173
        break;
    case NBD_CMD_WRITE:
        TRACE("Request type is WRITE");

P
Paolo Bonzini 已提交
1174
        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
N
Nick Thomas 已提交
1175
            TRACE("Server is read-only, return error");
1176 1177 1178 1179 1180 1181
            reply.error = EROFS;
            goto error_reply;
        }

        TRACE("Writing to device");

1182
        flags = 0;
1183
        if (request.flags & NBD_CMD_FLAG_FUA) {
1184 1185
            flags |= BDRV_REQ_FUA;
        }
1186
        ret = blk_pwrite(exp->blk, request.from + exp->dev_offset,
1187
                         req->data, request.len, flags);
1188 1189 1190 1191 1192
        if (ret < 0) {
            LOG("writing to file failed");
            reply.error = -ret;
            goto error_reply;
        }
N
Nick Thomas 已提交
1193

1194
        if (nbd_co_send_reply(req, &reply, 0) < 0) {
P
Paolo Bonzini 已提交
1195
            goto out;
1196
        }
N
Nick Thomas 已提交
1197
        break;
1198

N
Nick Thomas 已提交
1199
    case NBD_CMD_DISC:
1200 1201 1202
        /* unreachable, thanks to special case in nbd_co_receive_request() */
        abort();

P
Paolo Bonzini 已提交
1203 1204 1205
    case NBD_CMD_FLUSH:
        TRACE("Request type is FLUSH");

M
Max Reitz 已提交
1206
        ret = blk_co_flush(exp->blk);
P
Paolo Bonzini 已提交
1207 1208 1209 1210
        if (ret < 0) {
            LOG("flush failed");
            reply.error = -ret;
        }
1211
        if (nbd_co_send_reply(req, &reply, 0) < 0) {
P
Paolo Bonzini 已提交
1212
            goto out;
1213
        }
P
Paolo Bonzini 已提交
1214 1215 1216
        break;
    case NBD_CMD_TRIM:
        TRACE("Request type is TRIM");
1217 1218 1219 1220 1221
        ret = blk_co_pdiscard(exp->blk, request.from + exp->dev_offset,
                              request.len);
        if (ret < 0) {
            LOG("discard failed");
            reply.error = -ret;
P
Paolo Bonzini 已提交
1222
        }
1223
        if (nbd_co_send_reply(req, &reply, 0) < 0) {
P
Paolo Bonzini 已提交
1224
            goto out;
1225
        }
P
Paolo Bonzini 已提交
1226
        break;
N
Nick Thomas 已提交
1227
    default:
1228
        LOG("invalid request type (%" PRIu32 ") received", request.type);
Y
Yik Fang 已提交
1229
        reply.error = EINVAL;
1230
    error_reply:
1231 1232 1233 1234
        /* We must disconnect after NBD_CMD_WRITE if we did not
         * read the payload.
         */
        if (nbd_co_send_reply(req, &reply, 0) < 0 || !req->complete) {
P
Paolo Bonzini 已提交
1235
            goto out;
1236
        }
1237
        break;
N
Nick Thomas 已提交
1238 1239 1240 1241
    }

    TRACE("Request/Reply complete");

1242
done:
P
Paolo Bonzini 已提交
1243 1244 1245
    nbd_request_put(req);
    return;

P
Paolo Bonzini 已提交
1246
out:
1247
    nbd_request_put(req);
M
Max Reitz 已提交
1248
    client_close(client);
B
bellard 已提交
1249
}
P
Paolo Bonzini 已提交
1250

1251 1252 1253 1254
static void nbd_read(void *opaque)
{
    NBDClient *client = opaque;

P
Paolo Bonzini 已提交
1255
    if (client->recv_coroutine) {
1256
        qemu_coroutine_enter(client->recv_coroutine);
P
Paolo Bonzini 已提交
1257
    } else {
1258
        qemu_coroutine_enter(qemu_coroutine_create(nbd_trip, client));
1259 1260 1261
    }
}

P
Paolo Bonzini 已提交
1262 1263 1264 1265
static void nbd_restart_write(void *opaque)
{
    NBDClient *client = opaque;

1266
    qemu_coroutine_enter(client->send_coroutine);
P
Paolo Bonzini 已提交
1267 1268
}

M
Max Reitz 已提交
1269 1270 1271
static void nbd_set_handlers(NBDClient *client)
{
    if (client->exp && client->exp->ctx) {
1272
        aio_set_fd_handler(client->exp->ctx, client->sioc->fd,
1273
                           true,
M
Max Reitz 已提交
1274 1275 1276 1277 1278 1279 1280 1281 1282
                           client->can_read ? nbd_read : NULL,
                           client->send_coroutine ? nbd_restart_write : NULL,
                           client);
    }
}

static void nbd_unset_handlers(NBDClient *client)
{
    if (client->exp && client->exp->ctx) {
1283
        aio_set_fd_handler(client->exp->ctx, client->sioc->fd,
1284
                           true, NULL, NULL, NULL);
M
Max Reitz 已提交
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
    }
}

static void nbd_update_can_read(NBDClient *client)
{
    bool can_read = client->recv_coroutine ||
                    client->nb_requests < MAX_NBD_REQUESTS;

    if (can_read != client->can_read) {
        client->can_read = can_read;
        nbd_set_handlers(client);

        /* There is no need to invoke aio_notify(), since aio_set_fd_handler()
         * in nbd_set_handlers() will have taken care of that */
    }
}

1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
static coroutine_fn void nbd_co_client_start(void *opaque)
{
    NBDClientNewData *data = opaque;
    NBDClient *client = data->client;
    NBDExport *exp = client->exp;

    if (exp) {
        nbd_export_get(exp);
    }
    if (nbd_negotiate(data)) {
1312
        client_close(client);
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
        goto out;
    }
    qemu_co_mutex_init(&client->send_lock);
    nbd_set_handlers(client);

    if (exp) {
        QTAILQ_INSERT_TAIL(&exp->clients, client, next);
    }
out:
    g_free(data);
}

1325 1326
void nbd_client_new(NBDExport *exp,
                    QIOChannelSocket *sioc,
1327 1328
                    QCryptoTLSCreds *tlscreds,
                    const char *tlsaclname,
1329
                    void (*close_fn)(NBDClient *))
P
Paolo Bonzini 已提交
1330
{
1331
    NBDClient *client;
1332 1333
    NBDClientNewData *data = g_new(NBDClientNewData, 1);

1334 1335 1336
    client = g_malloc0(sizeof(NBDClient));
    client->refcount = 1;
    client->exp = exp;
1337 1338 1339 1340 1341
    client->tlscreds = tlscreds;
    if (tlscreds) {
        object_ref(OBJECT(client->tlscreds));
    }
    client->tlsaclname = g_strdup(tlsaclname);
1342 1343 1344 1345
    client->sioc = sioc;
    object_ref(OBJECT(client->sioc));
    client->ioc = QIO_CHANNEL(sioc);
    object_ref(OBJECT(client->ioc));
M
Max Reitz 已提交
1346
    client->can_read = true;
1347
    client->close = close_fn;
1348

1349
    data->client = client;
1350 1351
    data->co = qemu_coroutine_create(nbd_co_client_start, data);
    qemu_coroutine_enter(data->co);
P
Paolo Bonzini 已提交
1352
}