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
        return NBD_EPERM;
    case EIO:
        return NBD_EIO;
    case ENOMEM:
        return NBD_ENOMEM;
#ifdef EDQUOT
    case EDQUOT:
#endif
    case EFBIG:
    case ENOSPC:
        return NBD_ENOSPC;
42 43
    case ESHUTDOWN:
        return NBD_ESHUTDOWN;
44 45 46 47 48 49
    case EINVAL:
    default:
        return NBD_EINVAL;
    }
}

50 51
/* Definitions for opaque data types */

52
typedef struct NBDRequestData NBDRequestData;
53

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

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

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

    AioContext *ctx;
75

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

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

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

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

    Coroutine *recv_coroutine;

    CoMutex send_lock;
    Coroutine *send_coroutine;

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

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

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

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

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

   or

   Server         Client
   Negotiate #1
                  Option
   Negotiate #2

   ----

   followed by

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

B
bellard 已提交
132 133
*/

134 135 136 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,
                                      uint32_t opt, uint32_t len)
138 139 140
{
    uint64_t magic;

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

144
    magic = cpu_to_be64(NBD_REP_MAGIC);
145
    if (nbd_write(ioc, &magic, sizeof(magic), NULL) < 0) {
146 147
        LOG("write failed (rep magic)");
        return -EINVAL;
148
    }
149
    opt = cpu_to_be32(opt);
150
    if (nbd_write(ioc, &opt, sizeof(opt), NULL) < 0) {
151 152
        LOG("write failed (rep opt)");
        return -EINVAL;
153
    }
154
    type = cpu_to_be32(type);
155
    if (nbd_write(ioc, &type, sizeof(type), NULL) < 0) {
156 157
        LOG("write failed (rep type)");
        return -EINVAL;
158
    }
159
    len = cpu_to_be32(len);
160
    if (nbd_write(ioc, &len, sizeof(len), NULL) < 0) {
161 162
        LOG("write failed (rep data length)");
        return -EINVAL;
163
    }
164 165
    return 0;
}
166

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

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

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

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

216 217 218
    TRACE("Advertising export name '%s' description '%s'", name, desc);
    name_len = strlen(name);
    desc_len = strlen(desc);
219
    len = name_len + desc_len + sizeof(len);
220 221 222
    ret = nbd_negotiate_send_rep_len(ioc, NBD_REP_SERVER, NBD_OPT_LIST, len);
    if (ret < 0) {
        return ret;
223
    }
224

225
    len = cpu_to_be32(name_len);
226
    if (nbd_write(ioc, &len, sizeof(len), NULL) < 0) {
227 228 229
        LOG("write failed (name length)");
        return -EINVAL;
    }
230
    if (nbd_write(ioc, name, name_len, NULL) < 0) {
231
        LOG("write failed (name buffer)");
232 233
        return -EINVAL;
    }
234
    if (nbd_write(ioc, desc, desc_len, NULL) < 0) {
235
        LOG("write failed (description buffer)");
236 237 238 239 240
        return -EINVAL;
    }
    return 0;
}

241 242
/* Process the NBD_OPT_LIST command, with a potential series of replies.
 * Return -errno on error, 0 on success. */
243
static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length)
244 245 246 247
{
    NBDExport *exp;

    if (length) {
248
        if (nbd_drop(client->ioc, length, NULL) < 0) {
249 250
            return -EIO;
        }
251 252 253
        return nbd_negotiate_send_rep_err(client->ioc,
                                          NBD_REP_ERR_INVALID, NBD_OPT_LIST,
                                          "OPT_LIST should not have length");
254 255 256 257
    }

    /* For each export, send a NBD_REP_SERVER reply. */
    QTAILQ_FOREACH(exp, &exports, next) {
258
        if (nbd_negotiate_send_rep_list(client->ioc, exp)) {
259 260 261 262
            return -EINVAL;
        }
    }
    /* Finish with a NBD_REP_ACK. */
263
    return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, NBD_OPT_LIST);
264 265
}

266
static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length)
267
{
268
    char name[NBD_MAX_NAME_SIZE + 1];
269

270 271 272
    /* Client sends:
        [20 ..  xx]   export name (length bytes)
     */
273
    TRACE("Checking length");
274
    if (length >= sizeof(name)) {
275
        LOG("Bad length received");
276
        return -EINVAL;
277
    }
278
    if (nbd_read(client->ioc, name, length, NULL) < 0) {
279
        LOG("read failed");
280
        return -EINVAL;
281 282 283
    }
    name[length] = '\0';

284 285
    TRACE("Client requested export '%s'", name);

286 287 288
    client->exp = nbd_export_find(name);
    if (!client->exp) {
        LOG("export not found");
289
        return -EINVAL;
290 291 292 293
    }

    QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
    nbd_export_get(client->exp);
294 295

    return 0;
296 297
}

298 299
/* Handle NBD_OPT_STARTTLS. Return NULL to drop connection, or else the
 * new channel for all further (now-encrypted) communication. */
300 301 302 303 304 305 306 307 308 309
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) {
310
        if (nbd_drop(ioc, length, NULL) < 0) {
311 312
            return NULL;
        }
313 314
        nbd_negotiate_send_rep_err(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS,
                                   "OPT_STARTTLS should not have length");
315 316 317
        return NULL;
    }

318 319 320 321
    if (nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK,
                               NBD_OPT_STARTTLS) < 0) {
        return NULL;
    }
322 323 324 325 326 327 328 329 330

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

331
    qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
    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);
}


353 354
/* Process all NBD_OPT_* client option commands.
 * Return -errno on error, 0 on success. */
355
static int nbd_negotiate_options(NBDClient *client)
356
{
M
Max Reitz 已提交
357
    uint32_t flags;
358
    bool fixedNewstyle = false;
M
Max Reitz 已提交
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373

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

374
    if (nbd_read(client->ioc, &flags, sizeof(flags), NULL) < 0) {
M
Max Reitz 已提交
375 376 377 378 379
        LOG("read failed");
        return -EIO;
    }
    TRACE("Checking client flags");
    be32_to_cpus(&flags);
380
    if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
381
        TRACE("Client supports fixed newstyle handshake");
382 383 384
        fixedNewstyle = true;
        flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
    }
E
Eric Blake 已提交
385 386 387 388 389
    if (flags & NBD_FLAG_C_NO_ZEROES) {
        TRACE("Client supports no zeroes at handshake end");
        client->no_zeroes = true;
        flags &= ~NBD_FLAG_C_NO_ZEROES;
    }
390
    if (flags != 0) {
391
        TRACE("Unknown client flags 0x%" PRIx32 " received", flags);
M
Max Reitz 已提交
392 393 394
        return -EIO;
    }

395
    while (1) {
M
Max Reitz 已提交
396
        int ret;
397
        uint32_t clientflags, length;
398 399
        uint64_t magic;

400
        if (nbd_read(client->ioc, &magic, sizeof(magic), NULL) < 0) {
401 402 403 404 405 406 407 408 409
            LOG("read failed");
            return -EINVAL;
        }
        TRACE("Checking opts magic");
        if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {
            LOG("Bad magic received");
            return -EINVAL;
        }

410 411
        if (nbd_read(client->ioc, &clientflags,
                      sizeof(clientflags), NULL) < 0)
412
        {
413 414 415
            LOG("read failed");
            return -EINVAL;
        }
416
        clientflags = be32_to_cpu(clientflags);
417

418
        if (nbd_read(client->ioc, &length, sizeof(length), NULL) < 0) {
419 420 421 422 423
            LOG("read failed");
            return -EINVAL;
        }
        length = be32_to_cpu(length);

424
        TRACE("Checking option 0x%" PRIx32, clientflags);
425 426 427 428
        if (client->tlscreds &&
            client->ioc == (QIOChannel *)client->sioc) {
            QIOChannel *tioc;
            if (!fixedNewstyle) {
429
                TRACE("Unsupported option 0x%" PRIx32, clientflags);
430 431 432 433 434 435 436 437 438 439 440 441
                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;

442 443 444 445 446
            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;

447
            default:
448
                if (nbd_drop(client->ioc, length, NULL) < 0) {
449 450
                    return -EIO;
                }
451 452 453 454 455 456
                ret = nbd_negotiate_send_rep_err(client->ioc,
                                                 NBD_REP_ERR_TLS_REQD,
                                                 clientflags,
                                                 "Option 0x%" PRIx32
                                                 "not permitted before TLS",
                                                 clientflags);
457 458 459
                if (ret < 0) {
                    return ret;
                }
460 461 462 463
                /* Let the client keep trying, unless they asked to quit */
                if (clientflags == NBD_OPT_ABORT) {
                    return -EINVAL;
                }
464
                break;
465 466
            }
        } else if (fixedNewstyle) {
467 468 469 470 471 472 473 474 475
            switch (clientflags) {
            case NBD_OPT_LIST:
                ret = nbd_negotiate_handle_list(client, length);
                if (ret < 0) {
                    return ret;
                }
                break;

            case NBD_OPT_ABORT:
476 477 478 479
                /* NBD spec says we must try to reply before
                 * disconnecting, but that we must also tolerate
                 * guests that don't wait for our reply. */
                nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, clientflags);
480 481 482 483 484
                return -EINVAL;

            case NBD_OPT_EXPORT_NAME:
                return nbd_negotiate_handle_export_name(client, length);

485
            case NBD_OPT_STARTTLS:
486
                if (nbd_drop(client->ioc, length, NULL) < 0) {
487 488
                    return -EIO;
                }
489
                if (client->tlscreds) {
490 491 492 493
                    ret = nbd_negotiate_send_rep_err(client->ioc,
                                                     NBD_REP_ERR_INVALID,
                                                     clientflags,
                                                     "TLS already enabled");
494
                } else {
495 496 497 498
                    ret = nbd_negotiate_send_rep_err(client->ioc,
                                                     NBD_REP_ERR_POLICY,
                                                     clientflags,
                                                     "TLS not configured");
499 500 501
                }
                if (ret < 0) {
                    return ret;
502
                }
503
                break;
504
            default:
505
                if (nbd_drop(client->ioc, length, NULL) < 0) {
506 507
                    return -EIO;
                }
508 509 510 511 512 513
                ret = nbd_negotiate_send_rep_err(client->ioc,
                                                 NBD_REP_ERR_UNSUP,
                                                 clientflags,
                                                 "Unsupported option 0x%"
                                                 PRIx32,
                                                 clientflags);
514 515 516
                if (ret < 0) {
                    return ret;
                }
517
                break;
518 519 520 521 522 523 524 525 526 527 528
            }
        } 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:
529
                TRACE("Unsupported option 0x%" PRIx32, clientflags);
530
                return -EINVAL;
531
            }
532 533 534 535
        }
    }
}

536
static coroutine_fn int nbd_negotiate(NBDClient *client)
B
bellard 已提交
537
{
N
Nick Thomas 已提交
538
    char buf[8 + 8 + 8 + 128];
539
    int ret;
E
Eric Blake 已提交
540
    const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
541 542
                              NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
                              NBD_FLAG_SEND_WRITE_ZEROES);
543
    bool oldStyle;
E
Eric Blake 已提交
544
    size_t len;
N
Nick Thomas 已提交
545

546
    /* Old style negotiation header without options
547 548
        [ 0 ..   7]   passwd       ("NBDMAGIC")
        [ 8 ..  15]   magic        (NBD_CLIENT_MAGIC)
N
Nick Thomas 已提交
549
        [16 ..  23]   size
550
        [24 ..  25]   server flags (0)
H
Hani Benhabiles 已提交
551
        [26 ..  27]   export flags
552 553
        [28 .. 151]   reserved     (0)

554
       New style negotiation header with options
555 556 557
        [ 0 ..   7]   passwd       ("NBDMAGIC")
        [ 8 ..  15]   magic        (NBD_OPTS_MAGIC)
        [16 ..  17]   server flags (0)
558
        ....options sent....
559 560
        [18 ..  25]   size
        [26 ..  27]   export flags
E
Eric Blake 已提交
561
        [28 .. 151]   reserved     (0, omit if no_zeroes)
N
Nick Thomas 已提交
562 563
     */

564
    qio_channel_set_blocking(client->ioc, false, NULL);
565

N
Nick Thomas 已提交
566
    TRACE("Beginning negotiation.");
567
    memset(buf, 0, sizeof(buf));
N
Nick Thomas 已提交
568
    memcpy(buf, "NBDMAGIC", 8);
569 570 571

    oldStyle = client->exp != NULL && !client->tlscreds;
    if (oldStyle) {
572 573
        TRACE("advertising size %" PRIu64 " and flags %x",
              client->exp->size, client->exp->nbdflags | myflags);
J
John Snow 已提交
574 575 576
        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);
577
    } else {
J
John Snow 已提交
578
        stq_be_p(buf + 8, NBD_OPTS_MAGIC);
E
Eric Blake 已提交
579
        stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES);
580
    }
N
Nick Thomas 已提交
581

582 583 584
    if (oldStyle) {
        if (client->tlscreds) {
            TRACE("TLS cannot be enabled with oldstyle protocol");
585
            return -EINVAL;
586
        }
587
        if (nbd_write(client->ioc, buf, sizeof(buf), NULL) < 0) {
588
            LOG("write failed");
589
            return -EINVAL;
590 591
        }
    } else {
592
        if (nbd_write(client->ioc, buf, 18, NULL) < 0) {
593
            LOG("write failed");
594
            return -EINVAL;
595
        }
596 597
        ret = nbd_negotiate_options(client);
        if (ret != 0) {
598
            LOG("option negotiation failed");
599
            return ret;
600 601
        }

602 603
        TRACE("advertising size %" PRIu64 " and flags %x",
              client->exp->size, client->exp->nbdflags | myflags);
J
John Snow 已提交
604 605
        stq_be_p(buf + 18, client->exp->size);
        stw_be_p(buf + 26, client->exp->nbdflags | myflags);
E
Eric Blake 已提交
606
        len = client->no_zeroes ? 10 : sizeof(buf) - 18;
607 608
        ret = nbd_write(client->ioc, buf + 18, len, NULL);
        if (ret < 0) {
609
            LOG("write failed");
610
            return ret;
611
        }
N
Nick Thomas 已提交
612 613
    }

D
Dong Xu Wang 已提交
614
    TRACE("Negotiation succeeded.");
615 616

    return 0;
B
bellard 已提交
617 618
}

619
static int nbd_receive_request(QIOChannel *ioc, NBDRequest *request)
620
{
P
Paolo Bonzini 已提交
621
    uint8_t buf[NBD_REQUEST_SIZE];
N
Nick Thomas 已提交
622
    uint32_t magic;
623
    int ret;
N
Nick Thomas 已提交
624

625
    ret = nbd_read(ioc, buf, sizeof(buf), NULL);
626 627 628 629
    if (ret < 0) {
        return ret;
    }

N
Nick Thomas 已提交
630 631
    /* Request
       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
632 633
       [ 4 ..  5]   flags   (NBD_CMD_FLAG_FUA, ...)
       [ 6 ..  7]   type    (NBD_CMD_READ, ...)
N
Nick Thomas 已提交
634 635 636 637 638
       [ 8 .. 15]   handle
       [16 .. 23]   from
       [24 .. 27]   len
     */

639
    magic = ldl_be_p(buf);
640 641
    request->flags  = lduw_be_p(buf + 4);
    request->type   = lduw_be_p(buf + 6);
642 643 644
    request->handle = ldq_be_p(buf + 8);
    request->from   = ldq_be_p(buf + 16);
    request->len    = ldl_be_p(buf + 24);
N
Nick Thomas 已提交
645

646 647 648
    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 已提交
649 650

    if (magic != NBD_REQUEST_MAGIC) {
651
        LOG("invalid magic (got 0x%" PRIx32 ")", magic);
652
        return -EINVAL;
N
Nick Thomas 已提交
653 654
    }
    return 0;
655 656
}

657
static int nbd_send_reply(QIOChannel *ioc, NBDReply *reply)
658
{
P
Paolo Bonzini 已提交
659
    uint8_t buf[NBD_REPLY_SIZE];
N
Nick Thomas 已提交
660

661 662
    reply->error = system_errno_to_nbd_errno(reply->error);

663 664
    TRACE("Sending response to client: { .error = %" PRId32
          ", handle = %" PRIu64 " }",
665 666
          reply->error, reply->handle);

N
Nick Thomas 已提交
667 668 669 670 671
    /* Reply
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
       [ 4 ..  7]    error   (0 == no error)
       [ 7 .. 15]    handle
     */
J
John Snow 已提交
672 673 674
    stl_be_p(buf, NBD_REPLY_MAGIC);
    stl_be_p(buf + 4, reply->error);
    stq_be_p(buf + 8, reply->handle);
N
Nick Thomas 已提交
675

676
    return nbd_write(ioc, buf, sizeof(buf), NULL);
677
}
B
bellard 已提交
678

P
Paolo Bonzini 已提交
679 680
#define MAX_NBD_REQUESTS 16

681
void nbd_client_get(NBDClient *client)
682 683 684 685
{
    client->refcount++;
}

686
void nbd_client_put(NBDClient *client)
687 688
{
    if (--client->refcount == 0) {
689
        /* The last reference should be dropped by client->close,
M
Max Reitz 已提交
690
         * which is called by client_close.
691 692 693
         */
        assert(client->closing);

694
        qio_channel_detach_aio_context(client->ioc);
695 696
        object_unref(OBJECT(client->sioc));
        object_unref(OBJECT(client->ioc));
697 698 699 700
        if (client->tlscreds) {
            object_unref(OBJECT(client->tlscreds));
        }
        g_free(client->tlsaclname);
701 702 703 704
        if (client->exp) {
            QTAILQ_REMOVE(&client->exp->clients, client, next);
            nbd_export_put(client->exp);
        }
705 706 707 708
        g_free(client);
    }
}

709
static void client_close(NBDClient *client, bool negotiated)
710
{
711 712 713 714 715 716 717 718 719
    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.
     */
720 721
    qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH,
                         NULL);
722 723

    /* Also tell the client, so that they release their reference.  */
724 725
    if (client->close_fn) {
        client->close_fn(client, negotiated);
726 727 728
    }
}

729
static NBDRequestData *nbd_request_get(NBDClient *client)
P
Paolo Bonzini 已提交
730
{
731
    NBDRequestData *req;
732

P
Paolo Bonzini 已提交
733 734 735
    assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
    client->nb_requests++;

736
    req = g_new0(NBDRequestData, 1);
737 738
    nbd_client_get(client);
    req->client = client;
P
Paolo Bonzini 已提交
739 740 741
    return req;
}

742
static void nbd_request_put(NBDRequestData *req)
P
Paolo Bonzini 已提交
743
{
744
    NBDClient *client = req->client;
745

746 747 748
    if (req->data) {
        qemu_vfree(req->data);
    }
749
    g_free(req);
750

M
Max Reitz 已提交
751
    client->nb_requests--;
752 753
    nbd_client_receive_next_request(client);

754
    nbd_client_put(client);
P
Paolo Bonzini 已提交
755 756
}

M
Max Reitz 已提交
757
static void blk_aio_attached(AioContext *ctx, void *opaque)
M
Max Reitz 已提交
758 759 760 761 762 763 764 765 766
{
    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) {
767 768 769 770 771 772 773
        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 已提交
774 775 776
    }
}

M
Max Reitz 已提交
777
static void blk_aio_detach(void *opaque)
M
Max Reitz 已提交
778 779 780 781 782 783 784
{
    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) {
785
        qio_channel_detach_aio_context(client->ioc);
M
Max Reitz 已提交
786 787 788 789 790
    }

    exp->ctx = NULL;
}

791 792 793 794 795 796
static void nbd_eject_notifier(Notifier *n, void *data)
{
    NBDExport *exp = container_of(n, NBDExport, eject_notifier);
    nbd_export_close(exp);
}

797
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
E
Eric Blake 已提交
798
                          uint16_t nbdflags, void (*close)(NBDExport *),
799
                          bool writethrough, BlockBackend *on_eject_blk,
M
Max Reitz 已提交
800
                          Error **errp)
P
Paolo Bonzini 已提交
801
{
802
    BlockBackend *blk;
P
Paolo Bonzini 已提交
803
    NBDExport *exp = g_malloc0(sizeof(NBDExport));
804
    uint64_t perm;
805
    int ret;
806

807 808 809 810 811 812 813 814
    /* 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);
815 816 817 818
    ret = blk_insert_bs(blk, bs, errp);
    if (ret < 0) {
        goto fail;
    }
819 820
    blk_set_enable_write_cache(blk, !writethrough);

821
    exp->refcount = 1;
822
    QTAILQ_INIT(&exp->clients);
M
Max Reitz 已提交
823
    exp->blk = blk;
P
Paolo Bonzini 已提交
824 825
    exp->dev_offset = dev_offset;
    exp->nbdflags = nbdflags;
M
Max Reitz 已提交
826 827 828 829 830 831 832 833
    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;

834
    exp->close = close;
M
Max Reitz 已提交
835 836
    exp->ctx = blk_get_aio_context(blk);
    blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
837

838 839 840 841 842 843
    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);
    }
844

845 846
    /*
     * NBD exports are used for non-shared storage migration.  Make sure
847
     * that BDRV_O_INACTIVE is cleared and the image is ready for write
848 849
     * access since the export could be available before migration handover.
     */
850
    aio_context_acquire(exp->ctx);
M
Max Reitz 已提交
851
    blk_invalidate_cache(blk, NULL);
852
    aio_context_release(exp->ctx);
P
Paolo Bonzini 已提交
853
    return exp;
M
Max Reitz 已提交
854 855

fail:
856
    blk_unref(blk);
M
Max Reitz 已提交
857 858
    g_free(exp);
    return NULL;
P
Paolo Bonzini 已提交
859 860
}

P
Paolo Bonzini 已提交
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
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);
}

894 895 896 897 898 899
void nbd_export_set_description(NBDExport *exp, const char *description)
{
    g_free(exp->description);
    exp->description = g_strdup(description);
}

P
Paolo Bonzini 已提交
900 901
void nbd_export_close(NBDExport *exp)
{
902
    NBDClient *client, *next;
903

904 905
    nbd_export_get(exp);
    QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
906
        client_close(client, true);
907
    }
P
Paolo Bonzini 已提交
908
    nbd_export_set_name(exp, NULL);
909
    nbd_export_set_description(exp, NULL);
910
    nbd_export_put(exp);
911 912 913 914 915 916 917 918 919 920 921 922 923
}

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 已提交
924 925
    }

926
    if (--exp->refcount == 0) {
P
Paolo Bonzini 已提交
927
        assert(exp->name == NULL);
928
        assert(exp->description == NULL);
P
Paolo Bonzini 已提交
929

930 931 932 933
        if (exp->close) {
            exp->close(exp);
        }

934
        if (exp->blk) {
935 936 937 938
            if (exp->eject_notifier_blk) {
                notifier_remove(&exp->eject_notifier);
                blk_unref(exp->eject_notifier_blk);
            }
939 940 941 942 943 944
            blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
                                            blk_aio_detach, exp);
            blk_unref(exp->blk);
            exp->blk = NULL;
        }

945 946
        g_free(exp);
    }
P
Paolo Bonzini 已提交
947 948
}

949
BlockBackend *nbd_export_get_blockdev(NBDExport *exp)
P
Paolo Bonzini 已提交
950
{
M
Max Reitz 已提交
951
    return exp->blk;
P
Paolo Bonzini 已提交
952 953
}

P
Paolo Bonzini 已提交
954 955 956 957 958 959 960 961 962
void nbd_export_close_all(void)
{
    NBDExport *exp, *next;

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

963
static int nbd_co_send_reply(NBDRequestData *req, NBDReply *reply, int len)
964
{
965
    NBDClient *client = req->client;
966
    int ret;
967

968
    g_assert(qemu_in_coroutine());
P
Paolo Bonzini 已提交
969 970 971
    qemu_co_mutex_lock(&client->send_lock);
    client->send_coroutine = qemu_coroutine_self();

972
    if (!len) {
973
        ret = nbd_send_reply(client->ioc, reply);
974
    } else {
975
        qio_channel_set_cork(client->ioc, true);
976 977 978 979 980
        ret = nbd_send_reply(client->ioc, reply);
        if (ret == 0) {
            ret = nbd_write(client->ioc, req->data, len, NULL);
            if (ret < 0) {
                ret = -EIO;
981 982
            }
        }
983
        qio_channel_set_cork(client->ioc, false);
984
    }
P
Paolo Bonzini 已提交
985 986 987

    client->send_coroutine = NULL;
    qemu_co_mutex_unlock(&client->send_lock);
988
    return ret;
989 990
}

991 992 993 994 995 996
/* 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).
 */
997
static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request)
998
{
999
    NBDClient *client = req->client;
1000

1001
    g_assert(qemu_in_coroutine());
1002
    assert(client->recv_coroutine == qemu_coroutine_self());
1003 1004
    if (nbd_receive_request(client->ioc, request) < 0) {
        return -EIO;
1005 1006
    }

1007 1008
    TRACE("Decoding type");

1009
    if (request->type != NBD_CMD_WRITE) {
1010 1011 1012 1013
        /* No payload, we are ready to read the next request.  */
        req->complete = true;
    }

1014
    if (request->type == NBD_CMD_DISC) {
1015 1016 1017
        /* Special case: we're going to disconnect without a reply,
         * whether or not flags, from, or len are bogus */
        TRACE("Request type is DISCONNECT");
1018
        return -EIO;
1019 1020 1021 1022 1023
    }

    /* 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.  */
1024
    if ((request->from + request->len) < request->from) {
1025
        LOG("integer overflow detected, you're probably being attacked");
1026
        return -EINVAL;
1027 1028
    }

1029
    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE) {
1030
        if (request->len > NBD_MAX_BUFFER_SIZE) {
1031
            LOG("len (%" PRIu32" ) is larger than max len (%u)",
1032
                request->len, NBD_MAX_BUFFER_SIZE);
1033
            return -EINVAL;
1034 1035
        }

1036 1037
        req->data = blk_try_blockalign(client->exp->blk, request->len);
        if (req->data == NULL) {
1038
            return -ENOMEM;
1039
        }
1040
    }
1041
    if (request->type == NBD_CMD_WRITE) {
1042
        TRACE("Reading %" PRIu32 " byte(s)", request->len);
1043

1044
        if (nbd_read(client->ioc, req->data, request->len, NULL) < 0) {
1045
            LOG("reading from socket failed");
1046
            return -EIO;
1047
        }
1048
        req->complete = true;
1049
    }
1050 1051 1052 1053 1054 1055

    /* 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);
1056
        return request->type == NBD_CMD_WRITE ? -ENOSPC : -EINVAL;
1057
    }
1058
    if (request->flags & ~(NBD_CMD_FLAG_FUA | NBD_CMD_FLAG_NO_HOLE)) {
1059
        LOG("unsupported flags (got 0x%x)", request->flags);
1060
        return -EINVAL;
E
Eric Blake 已提交
1061
    }
1062 1063 1064
    if (request->type != NBD_CMD_WRITE_ZEROES &&
        (request->flags & NBD_CMD_FLAG_NO_HOLE)) {
        LOG("unexpected flags (got 0x%x)", request->flags);
1065
        return -EINVAL;
1066
    }
1067

1068
    return 0;
1069 1070
}

1071 1072
/* Owns a reference to the NBDClient passed as opaque.  */
static coroutine_fn void nbd_trip(void *opaque)
1073
{
P
Paolo Bonzini 已提交
1074
    NBDClient *client = opaque;
1075
    NBDExport *exp = client->exp;
1076
    NBDRequestData *req;
1077
    NBDRequest request = { 0 };    /* GCC thinks it can be used uninitialized */
1078
    NBDReply reply;
1079
    int ret;
1080
    int flags;
1081
    int reply_data_len = 0;
N
Nick Thomas 已提交
1082 1083

    TRACE("Reading request.");
1084
    if (client->closing) {
1085
        nbd_client_put(client);
1086 1087
        return;
    }
N
Nick Thomas 已提交
1088

1089
    req = nbd_request_get(client);
P
Paolo Bonzini 已提交
1090
    ret = nbd_co_receive_request(req, &request);
1091 1092
    client->recv_coroutine = NULL;
    nbd_client_receive_next_request(client);
1093
    if (ret == -EIO) {
1094
        goto disconnect;
1095
    }
N
Nick Thomas 已提交
1096

1097 1098 1099
    reply.handle = request.handle;
    reply.error = 0;

1100 1101
    if (ret < 0) {
        reply.error = -ret;
1102
        goto reply;
N
Nick Thomas 已提交
1103 1104
    }

1105 1106 1107 1108 1109 1110 1111 1112
    if (client->closing) {
        /*
         * The client may be closed when we are blocked in
         * nbd_co_receive_request()
         */
        goto done;
    }

1113
    switch (request.type) {
N
Nick Thomas 已提交
1114 1115 1116
    case NBD_CMD_READ:
        TRACE("Request type is READ");

1117 1118
        /* XXX: NBD Protocol only documents use of FUA with WRITE */
        if (request.flags & NBD_CMD_FLAG_FUA) {
M
Max Reitz 已提交
1119
            ret = blk_co_flush(exp->blk);
P
Paolo Bonzini 已提交
1120 1121 1122
            if (ret < 0) {
                LOG("flush failed");
                reply.error = -ret;
1123
                break;
P
Paolo Bonzini 已提交
1124 1125 1126
            }
        }

1127 1128
        ret = blk_pread(exp->blk, request.from + exp->dev_offset,
                        req->data, request.len);
1129
        if (ret < 0) {
N
Nick Thomas 已提交
1130
            LOG("reading from file failed");
1131
            reply.error = -ret;
1132
            break;
N
Nick Thomas 已提交
1133 1134
        }

1135
        reply_data_len = request.len;
1136
        TRACE("Read %" PRIu32" byte(s)", request.len);
1137

N
Nick Thomas 已提交
1138 1139 1140 1141
        break;
    case NBD_CMD_WRITE:
        TRACE("Request type is WRITE");

P
Paolo Bonzini 已提交
1142
        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
N
Nick Thomas 已提交
1143
            TRACE("Server is read-only, return error");
1144
            reply.error = EROFS;
1145
            break;
1146 1147 1148 1149
        }

        TRACE("Writing to device");

1150
        flags = 0;
1151
        if (request.flags & NBD_CMD_FLAG_FUA) {
1152 1153
            flags |= BDRV_REQ_FUA;
        }
1154
        ret = blk_pwrite(exp->blk, request.from + exp->dev_offset,
1155
                         req->data, request.len, flags);
1156 1157 1158 1159
        if (ret < 0) {
            LOG("writing to file failed");
            reply.error = -ret;
        }
N
Nick Thomas 已提交
1160

1161 1162 1163 1164 1165 1166 1167
        break;
    case NBD_CMD_WRITE_ZEROES:
        TRACE("Request type is WRITE_ZEROES");

        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
            TRACE("Server is read-only, return error");
            reply.error = EROFS;
1168
            break;
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
        }

        TRACE("Writing to device");

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

N
Nick Thomas 已提交
1187 1188
        break;
    case NBD_CMD_DISC:
1189 1190 1191
        /* unreachable, thanks to special case in nbd_co_receive_request() */
        abort();

P
Paolo Bonzini 已提交
1192 1193 1194
    case NBD_CMD_FLUSH:
        TRACE("Request type is FLUSH");

M
Max Reitz 已提交
1195
        ret = blk_co_flush(exp->blk);
P
Paolo Bonzini 已提交
1196 1197 1198 1199
        if (ret < 0) {
            LOG("flush failed");
            reply.error = -ret;
        }
1200

P
Paolo Bonzini 已提交
1201 1202 1203
        break;
    case NBD_CMD_TRIM:
        TRACE("Request type is TRIM");
1204 1205 1206 1207 1208
        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 已提交
1209
        }
1210

P
Paolo Bonzini 已提交
1211
        break;
N
Nick Thomas 已提交
1212
    default:
1213
        LOG("invalid request type (%" PRIu32 ") received", request.type);
Y
Yik Fang 已提交
1214
        reply.error = EINVAL;
1215 1216 1217 1218 1219 1220 1221 1222
    }

reply:
    /* We must disconnect after NBD_CMD_WRITE if we did not
     * read the payload.
     */
    if (nbd_co_send_reply(req, &reply, reply_data_len) < 0 || !req->complete) {
        goto disconnect;
N
Nick Thomas 已提交
1223 1224 1225 1226
    }

    TRACE("Request/Reply complete");

1227
done:
P
Paolo Bonzini 已提交
1228
    nbd_request_put(req);
1229
    nbd_client_put(client);
P
Paolo Bonzini 已提交
1230 1231
    return;

1232
disconnect:
1233
    nbd_request_put(req);
1234
    client_close(client, true);
1235
    nbd_client_put(client);
B
bellard 已提交
1236
}
P
Paolo Bonzini 已提交
1237

1238
static void nbd_client_receive_next_request(NBDClient *client)
M
Max Reitz 已提交
1239
{
1240 1241 1242 1243
    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 已提交
1244 1245 1246
    }
}

1247 1248
static coroutine_fn void nbd_co_client_start(void *opaque)
{
1249
    NBDClient *client = opaque;
1250 1251 1252 1253
    NBDExport *exp = client->exp;

    if (exp) {
        nbd_export_get(exp);
1254
        QTAILQ_INSERT_TAIL(&exp->clients, client, next);
1255
    }
1256 1257
    qemu_co_mutex_init(&client->send_lock);

1258
    if (nbd_negotiate(client)) {
1259
        client_close(client, false);
1260
        return;
1261
    }
1262 1263

    nbd_client_receive_next_request(client);
1264 1265
}

1266 1267 1268 1269 1270 1271
/*
 * 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.
 */
1272 1273
void nbd_client_new(NBDExport *exp,
                    QIOChannelSocket *sioc,
1274 1275
                    QCryptoTLSCreds *tlscreds,
                    const char *tlsaclname,
1276
                    void (*close_fn)(NBDClient *, bool))
P
Paolo Bonzini 已提交
1277
{
1278
    NBDClient *client;
1279
    Coroutine *co;
1280

1281 1282 1283
    client = g_malloc0(sizeof(NBDClient));
    client->refcount = 1;
    client->exp = exp;
1284 1285 1286 1287 1288
    client->tlscreds = tlscreds;
    if (tlscreds) {
        object_ref(OBJECT(client->tlscreds));
    }
    client->tlsaclname = g_strdup(tlsaclname);
1289 1290 1291 1292
    client->sioc = sioc;
    object_ref(OBJECT(client->sioc));
    client->ioc = QIO_CHANNEL(sioc);
    object_ref(OBJECT(client->ioc));
1293
    client->close_fn = close_fn;
1294

1295 1296
    co = qemu_coroutine_create(nbd_co_client_start, client);
    qemu_coroutine_enter(co);
P
Paolo Bonzini 已提交
1297
}