]> git.proxmox.com Git - mirror_qemu.git/blame - nbd/server.c
nbd/server: nbd_negotiate: fix error path
[mirror_qemu.git] / nbd / server.c
CommitLineData
75818250 1/*
b626b51a 2 * Copyright (C) 2016 Red Hat, Inc.
7a5ca864
FB
3 * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
4 *
798bfe00 5 * Network Block Device Server Side
7a5ca864
FB
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; under version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
75818250 18 */
7a5ca864 19
d38ea87a 20#include "qemu/osdep.h"
da34e65c 21#include "qapi/error.h"
798bfe00 22#include "nbd-internal.h"
ca441480
PB
23
24static int system_errno_to_nbd_errno(int err)
25{
26 switch (err) {
27 case 0:
28 return NBD_SUCCESS;
29 case EPERM:
c0301fcc 30 case EROFS:
ca441480
PB
31 return NBD_EPERM;
32 case EIO:
33 return NBD_EIO;
34 case ENOMEM:
35 return NBD_ENOMEM;
36#ifdef EDQUOT
37 case EDQUOT:
38#endif
39 case EFBIG:
40 case ENOSPC:
41 return NBD_ENOSPC;
b6f5d3b5
EB
42 case ESHUTDOWN:
43 return NBD_ESHUTDOWN;
ca441480
PB
44 case EINVAL:
45 default:
46 return NBD_EINVAL;
47 }
48}
49
9a304d29
PB
50/* Definitions for opaque data types */
51
315f78ab 52typedef struct NBDRequestData NBDRequestData;
9a304d29 53
315f78ab
EB
54struct NBDRequestData {
55 QSIMPLEQ_ENTRY(NBDRequestData) entry;
9a304d29
PB
56 NBDClient *client;
57 uint8_t *data;
29b6c3b3 58 bool complete;
9a304d29
PB
59};
60
61struct NBDExport {
2c8d9f06 62 int refcount;
0ddf08db
PB
63 void (*close)(NBDExport *exp);
64
aadf99a7 65 BlockBackend *blk;
ee0a19ec 66 char *name;
b1a75b33 67 char *description;
9a304d29
PB
68 off_t dev_offset;
69 off_t size;
7423f417 70 uint16_t nbdflags;
4b9441f6 71 QTAILQ_HEAD(, NBDClient) clients;
ee0a19ec 72 QTAILQ_ENTRY(NBDExport) next;
958c717d
HR
73
74 AioContext *ctx;
741cc431 75
cd7fca95 76 BlockBackend *eject_notifier_blk;
741cc431 77 Notifier eject_notifier;
9a304d29
PB
78};
79
ee0a19ec
PB
80static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
81
9a304d29
PB
82struct NBDClient {
83 int refcount;
0c9390d9 84 void (*close_fn)(NBDClient *client, bool negotiated);
9a304d29 85
c203c59a 86 bool no_zeroes;
9a304d29 87 NBDExport *exp;
f95910fe
DB
88 QCryptoTLSCreds *tlscreds;
89 char *tlsaclname;
1c778ef7
DB
90 QIOChannelSocket *sioc; /* The underlying data channel */
91 QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
9a304d29
PB
92
93 Coroutine *recv_coroutine;
94
95 CoMutex send_lock;
96 Coroutine *send_coroutine;
97
4b9441f6 98 QTAILQ_ENTRY(NBDClient) next;
9a304d29 99 int nb_requests;
ff2b68aa 100 bool closing;
9a304d29
PB
101};
102
7a5ca864
FB
103/* That's all folks */
104
ff82911c 105static void nbd_client_receive_next_request(NBDClient *client);
958c717d 106
6b8c01e7 107/* Basic flow for negotiation
7a5ca864
FB
108
109 Server Client
7a5ca864 110 Negotiate
6b8c01e7
PB
111
112 or
113
114 Server Client
115 Negotiate #1
116 Option
117 Negotiate #2
118
119 ----
120
121 followed by
122
123 Server Client
7a5ca864
FB
124 Request
125 Response
126 Request
127 Response
128 ...
129 ...
130 Request (type == 2)
6b8c01e7 131
7a5ca864
FB
132*/
133
526e5c65
EB
134/* Send a reply header, including length, but no payload.
135 * Return -errno on error, 0 on success. */
136static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
137 uint32_t opt, uint32_t len)
6b8c01e7 138{
6b8c01e7 139 uint64_t magic;
6b8c01e7 140
526e5c65
EB
141 TRACE("Reply opt=%" PRIx32 " type=%" PRIx32 " len=%" PRIu32,
142 type, opt, len);
f95910fe 143
f5076b5a 144 magic = cpu_to_be64(NBD_REP_MAGIC);
2b0bbc4f 145 if (nbd_write(ioc, &magic, sizeof(magic), NULL) < 0) {
f5076b5a
HB
146 LOG("write failed (rep magic)");
147 return -EINVAL;
6b8c01e7 148 }
f5076b5a 149 opt = cpu_to_be32(opt);
2b0bbc4f 150 if (nbd_write(ioc, &opt, sizeof(opt), NULL) < 0) {
f5076b5a
HB
151 LOG("write failed (rep opt)");
152 return -EINVAL;
6b8c01e7 153 }
f5076b5a 154 type = cpu_to_be32(type);
2b0bbc4f 155 if (nbd_write(ioc, &type, sizeof(type), NULL) < 0) {
f5076b5a
HB
156 LOG("write failed (rep type)");
157 return -EINVAL;
6b8c01e7 158 }
526e5c65 159 len = cpu_to_be32(len);
2b0bbc4f 160 if (nbd_write(ioc, &len, sizeof(len), NULL) < 0) {
f5076b5a
HB
161 LOG("write failed (rep data length)");
162 return -EINVAL;
6b8c01e7 163 }
f5076b5a
HB
164 return 0;
165}
6b8c01e7 166
526e5c65
EB
167/* Send a reply header with default 0 length.
168 * Return -errno on error, 0 on success. */
169static int nbd_negotiate_send_rep(QIOChannel *ioc, uint32_t type, uint32_t opt)
170{
171 return nbd_negotiate_send_rep_len(ioc, type, opt, 0);
172}
173
36683283
EB
174/* Send an error reply.
175 * Return -errno on error, 0 on success. */
176static int GCC_FMT_ATTR(4, 5)
177nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
178 uint32_t opt, const char *fmt, ...)
179{
180 va_list va;
181 char *msg;
182 int ret;
183 size_t len;
184
185 va_start(va, fmt);
186 msg = g_strdup_vprintf(fmt, va);
187 va_end(va);
188 len = strlen(msg);
189 assert(len < 4096);
190 TRACE("sending error message \"%s\"", msg);
191 ret = nbd_negotiate_send_rep_len(ioc, type, opt, len);
192 if (ret < 0) {
193 goto out;
194 }
2b0bbc4f 195 if (nbd_write(ioc, msg, len, NULL) < 0) {
36683283
EB
196 LOG("write failed (error message)");
197 ret = -EIO;
198 } else {
199 ret = 0;
200 }
201out:
202 g_free(msg);
203 return ret;
204}
205
526e5c65
EB
206/* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
207 * Return -errno on error, 0 on success. */
1c778ef7 208static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp)
32d7d2e0 209{
b1a75b33 210 size_t name_len, desc_len;
526e5c65 211 uint32_t len;
b1a75b33
EB
212 const char *name = exp->name ? exp->name : "";
213 const char *desc = exp->description ? exp->description : "";
526e5c65 214 int rc;
32d7d2e0 215
b1a75b33
EB
216 TRACE("Advertising export name '%s' description '%s'", name, desc);
217 name_len = strlen(name);
218 desc_len = strlen(desc);
526e5c65
EB
219 len = name_len + desc_len + sizeof(len);
220 rc = nbd_negotiate_send_rep_len(ioc, NBD_REP_SERVER, NBD_OPT_LIST, len);
221 if (rc < 0) {
222 return rc;
32d7d2e0 223 }
526e5c65 224
32d7d2e0 225 len = cpu_to_be32(name_len);
2b0bbc4f 226 if (nbd_write(ioc, &len, sizeof(len), NULL) < 0) {
b1a75b33
EB
227 LOG("write failed (name length)");
228 return -EINVAL;
229 }
2b0bbc4f 230 if (nbd_write(ioc, name, name_len, NULL) < 0) {
b1a75b33 231 LOG("write failed (name buffer)");
32d7d2e0
HB
232 return -EINVAL;
233 }
2b0bbc4f 234 if (nbd_write(ioc, desc, desc_len, NULL) < 0) {
b1a75b33 235 LOG("write failed (description buffer)");
32d7d2e0
HB
236 return -EINVAL;
237 }
238 return 0;
239}
240
526e5c65
EB
241/* Process the NBD_OPT_LIST command, with a potential series of replies.
242 * Return -errno on error, 0 on success. */
1a6245a5 243static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length)
32d7d2e0 244{
32d7d2e0
HB
245 NBDExport *exp;
246
32d7d2e0 247 if (length) {
2b0bbc4f 248 if (nbd_drop(client->ioc, length, NULL) < 0) {
0379f474
HR
249 return -EIO;
250 }
36683283
EB
251 return nbd_negotiate_send_rep_err(client->ioc,
252 NBD_REP_ERR_INVALID, NBD_OPT_LIST,
253 "OPT_LIST should not have length");
32d7d2e0
HB
254 }
255
256 /* For each export, send a NBD_REP_SERVER reply. */
257 QTAILQ_FOREACH(exp, &exports, next) {
1c778ef7 258 if (nbd_negotiate_send_rep_list(client->ioc, exp)) {
32d7d2e0
HB
259 return -EINVAL;
260 }
261 }
262 /* Finish with a NBD_REP_ACK. */
1c778ef7 263 return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, NBD_OPT_LIST);
32d7d2e0
HB
264}
265
1a6245a5 266static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length)
f5076b5a 267{
1c778ef7 268 int rc = -EINVAL;
943cec86 269 char name[NBD_MAX_NAME_SIZE + 1];
6b8c01e7 270
f5076b5a
HB
271 /* Client sends:
272 [20 .. xx] export name (length bytes)
273 */
6b8c01e7 274 TRACE("Checking length");
943cec86 275 if (length >= sizeof(name)) {
6b8c01e7
PB
276 LOG("Bad length received");
277 goto fail;
278 }
2b0bbc4f 279 if (nbd_read(client->ioc, name, length, NULL) < 0) {
6b8c01e7
PB
280 LOG("read failed");
281 goto fail;
282 }
283 name[length] = '\0';
284
9344e5f5
DB
285 TRACE("Client requested export '%s'", name);
286
6b8c01e7
PB
287 client->exp = nbd_export_find(name);
288 if (!client->exp) {
289 LOG("export not found");
290 goto fail;
291 }
292
293 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
294 nbd_export_get(client->exp);
6b8c01e7
PB
295 rc = 0;
296fail:
297 return rc;
298}
299
36683283
EB
300/* Handle NBD_OPT_STARTTLS. Return NULL to drop connection, or else the
301 * new channel for all further (now-encrypted) communication. */
f95910fe
DB
302static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
303 uint32_t length)
304{
305 QIOChannel *ioc;
306 QIOChannelTLS *tioc;
307 struct NBDTLSHandshakeData data = { 0 };
308
309 TRACE("Setting up TLS");
310 ioc = client->ioc;
311 if (length) {
2b0bbc4f 312 if (nbd_drop(ioc, length, NULL) < 0) {
f95910fe
DB
313 return NULL;
314 }
36683283
EB
315 nbd_negotiate_send_rep_err(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS,
316 "OPT_STARTTLS should not have length");
f95910fe
DB
317 return NULL;
318 }
319
63d5ef86
EB
320 if (nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK,
321 NBD_OPT_STARTTLS) < 0) {
322 return NULL;
323 }
f95910fe
DB
324
325 tioc = qio_channel_tls_new_server(ioc,
326 client->tlscreds,
327 client->tlsaclname,
328 NULL);
329 if (!tioc) {
330 return NULL;
331 }
332
0d73f725 333 qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
f95910fe
DB
334 TRACE("Starting TLS handshake");
335 data.loop = g_main_loop_new(g_main_context_default(), FALSE);
336 qio_channel_tls_handshake(tioc,
337 nbd_tls_handshake,
338 &data,
339 NULL);
340
341 if (!data.complete) {
342 g_main_loop_run(data.loop);
343 }
344 g_main_loop_unref(data.loop);
345 if (data.error) {
346 object_unref(OBJECT(tioc));
347 error_free(data.error);
348 return NULL;
349 }
350
351 return QIO_CHANNEL(tioc);
352}
353
354
526e5c65
EB
355/* Process all NBD_OPT_* client option commands.
356 * Return -errno on error, 0 on success. */
1a6245a5 357static int nbd_negotiate_options(NBDClient *client)
f5076b5a 358{
9c122ada 359 uint32_t flags;
26afa868 360 bool fixedNewstyle = false;
9c122ada
HR
361
362 /* Client sends:
363 [ 0 .. 3] client flags
364
365 [ 0 .. 7] NBD_OPTS_MAGIC
366 [ 8 .. 11] NBD option
367 [12 .. 15] Data length
368 ... Rest of request
369
370 [ 0 .. 7] NBD_OPTS_MAGIC
371 [ 8 .. 11] Second NBD option
372 [12 .. 15] Data length
373 ... Rest of request
374 */
375
2b0bbc4f 376 if (nbd_read(client->ioc, &flags, sizeof(flags), NULL) < 0) {
9c122ada
HR
377 LOG("read failed");
378 return -EIO;
379 }
380 TRACE("Checking client flags");
381 be32_to_cpus(&flags);
26afa868 382 if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
2cb34749 383 TRACE("Client supports fixed newstyle handshake");
26afa868
DB
384 fixedNewstyle = true;
385 flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
386 }
c203c59a
EB
387 if (flags & NBD_FLAG_C_NO_ZEROES) {
388 TRACE("Client supports no zeroes at handshake end");
389 client->no_zeroes = true;
390 flags &= ~NBD_FLAG_C_NO_ZEROES;
391 }
26afa868 392 if (flags != 0) {
2cb34749 393 TRACE("Unknown client flags 0x%" PRIx32 " received", flags);
9c122ada
HR
394 return -EIO;
395 }
396
f5076b5a 397 while (1) {
9c122ada 398 int ret;
26afa868 399 uint32_t clientflags, length;
f5076b5a
HB
400 uint64_t magic;
401
2b0bbc4f 402 if (nbd_read(client->ioc, &magic, sizeof(magic), NULL) < 0) {
f5076b5a
HB
403 LOG("read failed");
404 return -EINVAL;
405 }
406 TRACE("Checking opts magic");
407 if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) {
408 LOG("Bad magic received");
409 return -EINVAL;
410 }
411
2b0bbc4f
VSO
412 if (nbd_read(client->ioc, &clientflags,
413 sizeof(clientflags), NULL) < 0)
f5d406fe 414 {
f5076b5a
HB
415 LOG("read failed");
416 return -EINVAL;
417 }
26afa868 418 clientflags = be32_to_cpu(clientflags);
f5076b5a 419
2b0bbc4f 420 if (nbd_read(client->ioc, &length, sizeof(length), NULL) < 0) {
f5076b5a
HB
421 LOG("read failed");
422 return -EINVAL;
423 }
424 length = be32_to_cpu(length);
425
2cb34749 426 TRACE("Checking option 0x%" PRIx32, clientflags);
f95910fe
DB
427 if (client->tlscreds &&
428 client->ioc == (QIOChannel *)client->sioc) {
429 QIOChannel *tioc;
430 if (!fixedNewstyle) {
2cb34749 431 TRACE("Unsupported option 0x%" PRIx32, clientflags);
f95910fe
DB
432 return -EINVAL;
433 }
434 switch (clientflags) {
435 case NBD_OPT_STARTTLS:
436 tioc = nbd_negotiate_handle_starttls(client, length);
437 if (!tioc) {
438 return -EIO;
439 }
440 object_unref(OBJECT(client->ioc));
441 client->ioc = QIO_CHANNEL(tioc);
442 break;
443
d1129a8a
EB
444 case NBD_OPT_EXPORT_NAME:
445 /* No way to return an error to client, so drop connection */
446 TRACE("Option 0x%x not permitted before TLS", clientflags);
447 return -EINVAL;
448
f95910fe 449 default:
2b0bbc4f 450 if (nbd_drop(client->ioc, length, NULL) < 0) {
d1129a8a
EB
451 return -EIO;
452 }
36683283
EB
453 ret = nbd_negotiate_send_rep_err(client->ioc,
454 NBD_REP_ERR_TLS_REQD,
455 clientflags,
456 "Option 0x%" PRIx32
457 "not permitted before TLS",
458 clientflags);
63d5ef86
EB
459 if (ret < 0) {
460 return ret;
461 }
b6f5d3b5
EB
462 /* Let the client keep trying, unless they asked to quit */
463 if (clientflags == NBD_OPT_ABORT) {
464 return -EINVAL;
465 }
d1129a8a 466 break;
f95910fe
DB
467 }
468 } else if (fixedNewstyle) {
26afa868
DB
469 switch (clientflags) {
470 case NBD_OPT_LIST:
471 ret = nbd_negotiate_handle_list(client, length);
472 if (ret < 0) {
473 return ret;
474 }
475 break;
476
477 case NBD_OPT_ABORT:
b6f5d3b5
EB
478 /* NBD spec says we must try to reply before
479 * disconnecting, but that we must also tolerate
480 * guests that don't wait for our reply. */
481 nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, clientflags);
26afa868
DB
482 return -EINVAL;
483
484 case NBD_OPT_EXPORT_NAME:
485 return nbd_negotiate_handle_export_name(client, length);
486
f95910fe 487 case NBD_OPT_STARTTLS:
2b0bbc4f 488 if (nbd_drop(client->ioc, length, NULL) < 0) {
d1129a8a
EB
489 return -EIO;
490 }
f95910fe 491 if (client->tlscreds) {
36683283
EB
492 ret = nbd_negotiate_send_rep_err(client->ioc,
493 NBD_REP_ERR_INVALID,
494 clientflags,
495 "TLS already enabled");
f95910fe 496 } else {
36683283
EB
497 ret = nbd_negotiate_send_rep_err(client->ioc,
498 NBD_REP_ERR_POLICY,
499 clientflags,
500 "TLS not configured");
63d5ef86
EB
501 }
502 if (ret < 0) {
503 return ret;
f95910fe 504 }
d1129a8a 505 break;
26afa868 506 default:
2b0bbc4f 507 if (nbd_drop(client->ioc, length, NULL) < 0) {
156f6a10
EB
508 return -EIO;
509 }
36683283
EB
510 ret = nbd_negotiate_send_rep_err(client->ioc,
511 NBD_REP_ERR_UNSUP,
512 clientflags,
513 "Unsupported option 0x%"
514 PRIx32,
515 clientflags);
63d5ef86
EB
516 if (ret < 0) {
517 return ret;
518 }
156f6a10 519 break;
26afa868
DB
520 }
521 } else {
522 /*
523 * If broken new-style we should drop the connection
524 * for anything except NBD_OPT_EXPORT_NAME
525 */
526 switch (clientflags) {
527 case NBD_OPT_EXPORT_NAME:
528 return nbd_negotiate_handle_export_name(client, length);
529
530 default:
2cb34749 531 TRACE("Unsupported option 0x%" PRIx32, clientflags);
26afa868 532 return -EINVAL;
32d7d2e0 533 }
f5076b5a
HB
534 }
535 }
536}
537
c84087f2 538static coroutine_fn int nbd_negotiate(NBDClient *client)
7a5ca864 539{
b2e3d87f 540 char buf[8 + 8 + 8 + 128];
185b4338 541 int rc;
7423f417 542 const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
1f4d6d18
EB
543 NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
544 NBD_FLAG_SEND_WRITE_ZEROES);
f95910fe 545 bool oldStyle;
c203c59a 546 size_t len;
b2e3d87f 547
f95910fe 548 /* Old style negotiation header without options
6b8c01e7
PB
549 [ 0 .. 7] passwd ("NBDMAGIC")
550 [ 8 .. 15] magic (NBD_CLIENT_MAGIC)
b2e3d87f 551 [16 .. 23] size
6b8c01e7 552 [24 .. 25] server flags (0)
5672ee54 553 [26 .. 27] export flags
6b8c01e7
PB
554 [28 .. 151] reserved (0)
555
f95910fe 556 New style negotiation header with options
6b8c01e7
PB
557 [ 0 .. 7] passwd ("NBDMAGIC")
558 [ 8 .. 15] magic (NBD_OPTS_MAGIC)
559 [16 .. 17] server flags (0)
f95910fe 560 ....options sent....
6b8c01e7
PB
561 [18 .. 25] size
562 [26 .. 27] export flags
c203c59a 563 [28 .. 151] reserved (0, omit if no_zeroes)
b2e3d87f
NT
564 */
565
1c778ef7 566 qio_channel_set_blocking(client->ioc, false, NULL);
185b4338
PB
567 rc = -EINVAL;
568
b2e3d87f 569 TRACE("Beginning negotiation.");
8ffaaba0 570 memset(buf, 0, sizeof(buf));
b2e3d87f 571 memcpy(buf, "NBDMAGIC", 8);
f95910fe
DB
572
573 oldStyle = client->exp != NULL && !client->tlscreds;
574 if (oldStyle) {
2cb34749
EB
575 TRACE("advertising size %" PRIu64 " and flags %x",
576 client->exp->size, client->exp->nbdflags | myflags);
667ad26f
JS
577 stq_be_p(buf + 8, NBD_CLIENT_MAGIC);
578 stq_be_p(buf + 16, client->exp->size);
579 stw_be_p(buf + 26, client->exp->nbdflags | myflags);
6b8c01e7 580 } else {
667ad26f 581 stq_be_p(buf + 8, NBD_OPTS_MAGIC);
c203c59a 582 stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES);
6b8c01e7 583 }
b2e3d87f 584
f95910fe
DB
585 if (oldStyle) {
586 if (client->tlscreds) {
587 TRACE("TLS cannot be enabled with oldstyle protocol");
588 goto fail;
589 }
2b0bbc4f 590 if (nbd_write(client->ioc, buf, sizeof(buf), NULL) < 0) {
6b8c01e7
PB
591 LOG("write failed");
592 goto fail;
593 }
594 } else {
2b0bbc4f 595 if (nbd_write(client->ioc, buf, 18, NULL) < 0) {
6b8c01e7
PB
596 LOG("write failed");
597 goto fail;
598 }
1a6245a5 599 rc = nbd_negotiate_options(client);
f5076b5a 600 if (rc != 0) {
6b8c01e7
PB
601 LOG("option negotiation failed");
602 goto fail;
603 }
604
2cb34749
EB
605 TRACE("advertising size %" PRIu64 " and flags %x",
606 client->exp->size, client->exp->nbdflags | myflags);
667ad26f
JS
607 stq_be_p(buf + 18, client->exp->size);
608 stw_be_p(buf + 26, client->exp->nbdflags | myflags);
c203c59a 609 len = client->no_zeroes ? 10 : sizeof(buf) - 18;
7798d3aa
VSO
610 rc = nbd_write(client->ioc, buf + 18, len, NULL);
611 if (rc < 0) {
6b8c01e7
PB
612 LOG("write failed");
613 goto fail;
614 }
b2e3d87f
NT
615 }
616
07f35073 617 TRACE("Negotiation succeeded.");
185b4338
PB
618 rc = 0;
619fail:
620 return rc;
7a5ca864
FB
621}
622
a0dc63a6 623static int nbd_receive_request(QIOChannel *ioc, NBDRequest *request)
75818250 624{
fa26c26b 625 uint8_t buf[NBD_REQUEST_SIZE];
b2e3d87f 626 uint32_t magic;
a0dc63a6 627 int ret;
b2e3d87f 628
d1fdf257 629 ret = nbd_read(ioc, buf, sizeof(buf), NULL);
185b4338
PB
630 if (ret < 0) {
631 return ret;
632 }
633
b2e3d87f
NT
634 /* Request
635 [ 0 .. 3] magic (NBD_REQUEST_MAGIC)
b626b51a
EB
636 [ 4 .. 5] flags (NBD_CMD_FLAG_FUA, ...)
637 [ 6 .. 7] type (NBD_CMD_READ, ...)
b2e3d87f
NT
638 [ 8 .. 15] handle
639 [16 .. 23] from
640 [24 .. 27] len
641 */
642
773dce3c 643 magic = ldl_be_p(buf);
b626b51a
EB
644 request->flags = lduw_be_p(buf + 4);
645 request->type = lduw_be_p(buf + 6);
773dce3c
PM
646 request->handle = ldq_be_p(buf + 8);
647 request->from = ldq_be_p(buf + 16);
648 request->len = ldl_be_p(buf + 24);
b2e3d87f 649
b626b51a
EB
650 TRACE("Got request: { magic = 0x%" PRIx32 ", .flags = %" PRIx16
651 ", .type = %" PRIx16 ", from = %" PRIu64 ", len = %" PRIu32 " }",
652 magic, request->flags, request->type, request->from, request->len);
b2e3d87f
NT
653
654 if (magic != NBD_REQUEST_MAGIC) {
2cb34749 655 LOG("invalid magic (got 0x%" PRIx32 ")", magic);
185b4338 656 return -EINVAL;
b2e3d87f
NT
657 }
658 return 0;
75818250
TS
659}
660
a0dc63a6 661static int nbd_send_reply(QIOChannel *ioc, NBDReply *reply)
75818250 662{
fa26c26b 663 uint8_t buf[NBD_REPLY_SIZE];
b2e3d87f 664
ca441480
PB
665 reply->error = system_errno_to_nbd_errno(reply->error);
666
2cb34749
EB
667 TRACE("Sending response to client: { .error = %" PRId32
668 ", handle = %" PRIu64 " }",
7548fe31
EB
669 reply->error, reply->handle);
670
b2e3d87f
NT
671 /* Reply
672 [ 0 .. 3] magic (NBD_REPLY_MAGIC)
673 [ 4 .. 7] error (0 == no error)
674 [ 7 .. 15] handle
675 */
667ad26f
JS
676 stl_be_p(buf, NBD_REPLY_MAGIC);
677 stl_be_p(buf + 4, reply->error);
678 stq_be_p(buf + 8, reply->handle);
b2e3d87f 679
d1fdf257 680 return nbd_write(ioc, buf, sizeof(buf), NULL);
75818250 681}
7a5ca864 682
41996e38
PB
683#define MAX_NBD_REQUESTS 16
684
ce33967a 685void nbd_client_get(NBDClient *client)
1743b515
PB
686{
687 client->refcount++;
688}
689
ce33967a 690void nbd_client_put(NBDClient *client)
1743b515
PB
691{
692 if (--client->refcount == 0) {
ff2b68aa 693 /* The last reference should be dropped by client->close,
f53a829b 694 * which is called by client_close.
ff2b68aa
PB
695 */
696 assert(client->closing);
697
ff82911c 698 qio_channel_detach_aio_context(client->ioc);
1c778ef7
DB
699 object_unref(OBJECT(client->sioc));
700 object_unref(OBJECT(client->ioc));
f95910fe
DB
701 if (client->tlscreds) {
702 object_unref(OBJECT(client->tlscreds));
703 }
704 g_free(client->tlsaclname);
6b8c01e7
PB
705 if (client->exp) {
706 QTAILQ_REMOVE(&client->exp->clients, client, next);
707 nbd_export_put(client->exp);
708 }
1743b515
PB
709 g_free(client);
710 }
711}
712
0c9390d9 713static void client_close(NBDClient *client, bool negotiated)
1743b515 714{
ff2b68aa
PB
715 if (client->closing) {
716 return;
717 }
718
719 client->closing = true;
720
721 /* Force requests to finish. They will drop their own references,
722 * then we'll close the socket and free the NBDClient.
723 */
1c778ef7
DB
724 qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH,
725 NULL);
ff2b68aa
PB
726
727 /* Also tell the client, so that they release their reference. */
0c9390d9
EB
728 if (client->close_fn) {
729 client->close_fn(client, negotiated);
1743b515 730 }
1743b515
PB
731}
732
315f78ab 733static NBDRequestData *nbd_request_get(NBDClient *client)
d9a73806 734{
315f78ab 735 NBDRequestData *req;
72deddc5 736
41996e38
PB
737 assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
738 client->nb_requests++;
739
315f78ab 740 req = g_new0(NBDRequestData, 1);
72deddc5
PB
741 nbd_client_get(client);
742 req->client = client;
d9a73806
PB
743 return req;
744}
745
315f78ab 746static void nbd_request_put(NBDRequestData *req)
d9a73806 747{
72deddc5 748 NBDClient *client = req->client;
e1adb27a 749
2d821488
SH
750 if (req->data) {
751 qemu_vfree(req->data);
752 }
1729404c 753 g_free(req);
e1adb27a 754
958c717d 755 client->nb_requests--;
ff82911c
PB
756 nbd_client_receive_next_request(client);
757
72deddc5 758 nbd_client_put(client);
d9a73806
PB
759}
760
aadf99a7 761static void blk_aio_attached(AioContext *ctx, void *opaque)
f2149281
HR
762{
763 NBDExport *exp = opaque;
764 NBDClient *client;
765
766 TRACE("Export %s: Attaching clients to AIO context %p\n", exp->name, ctx);
767
768 exp->ctx = ctx;
769
770 QTAILQ_FOREACH(client, &exp->clients, next) {
ff82911c
PB
771 qio_channel_attach_aio_context(client->ioc, ctx);
772 if (client->recv_coroutine) {
773 aio_co_schedule(ctx, client->recv_coroutine);
774 }
775 if (client->send_coroutine) {
776 aio_co_schedule(ctx, client->send_coroutine);
777 }
f2149281
HR
778 }
779}
780
aadf99a7 781static void blk_aio_detach(void *opaque)
f2149281
HR
782{
783 NBDExport *exp = opaque;
784 NBDClient *client;
785
786 TRACE("Export %s: Detaching clients from AIO context %p\n", exp->name, exp->ctx);
787
788 QTAILQ_FOREACH(client, &exp->clients, next) {
ff82911c 789 qio_channel_detach_aio_context(client->ioc);
f2149281
HR
790 }
791
792 exp->ctx = NULL;
793}
794
741cc431
HR
795static void nbd_eject_notifier(Notifier *n, void *data)
796{
797 NBDExport *exp = container_of(n, NBDExport, eject_notifier);
798 nbd_export_close(exp);
799}
800
cd7fca95 801NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
7423f417 802 uint16_t nbdflags, void (*close)(NBDExport *),
cd7fca95 803 bool writethrough, BlockBackend *on_eject_blk,
98f44bbe 804 Error **errp)
af49bbbe 805{
cd7fca95 806 BlockBackend *blk;
af49bbbe 807 NBDExport *exp = g_malloc0(sizeof(NBDExport));
8a7ce4f9 808 uint64_t perm;
d7086422 809 int ret;
cd7fca95 810
8a7ce4f9
KW
811 /* Don't allow resize while the NBD server is running, otherwise we don't
812 * care what happens with the node. */
813 perm = BLK_PERM_CONSISTENT_READ;
814 if ((nbdflags & NBD_FLAG_READ_ONLY) == 0) {
815 perm |= BLK_PERM_WRITE;
816 }
817 blk = blk_new(perm, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
818 BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD);
d7086422
KW
819 ret = blk_insert_bs(blk, bs, errp);
820 if (ret < 0) {
821 goto fail;
822 }
cd7fca95
KW
823 blk_set_enable_write_cache(blk, !writethrough);
824
2c8d9f06 825 exp->refcount = 1;
4b9441f6 826 QTAILQ_INIT(&exp->clients);
aadf99a7 827 exp->blk = blk;
af49bbbe
PB
828 exp->dev_offset = dev_offset;
829 exp->nbdflags = nbdflags;
98f44bbe
HR
830 exp->size = size < 0 ? blk_getlength(blk) : size;
831 if (exp->size < 0) {
832 error_setg_errno(errp, -exp->size,
833 "Failed to determine the NBD export's length");
834 goto fail;
835 }
836 exp->size -= exp->size % BDRV_SECTOR_SIZE;
837
0ddf08db 838 exp->close = close;
aadf99a7 839 exp->ctx = blk_get_aio_context(blk);
aadf99a7 840 blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
741cc431 841
cd7fca95
KW
842 if (on_eject_blk) {
843 blk_ref(on_eject_blk);
844 exp->eject_notifier_blk = on_eject_blk;
845 exp->eject_notifier.notify = nbd_eject_notifier;
846 blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier);
847 }
741cc431 848
7ea2d269
AK
849 /*
850 * NBD exports are used for non-shared storage migration. Make sure
04c01a5c 851 * that BDRV_O_INACTIVE is cleared and the image is ready for write
7ea2d269
AK
852 * access since the export could be available before migration handover.
853 */
e5f3e12e 854 aio_context_acquire(exp->ctx);
aadf99a7 855 blk_invalidate_cache(blk, NULL);
e5f3e12e 856 aio_context_release(exp->ctx);
af49bbbe 857 return exp;
98f44bbe
HR
858
859fail:
cd7fca95 860 blk_unref(blk);
98f44bbe
HR
861 g_free(exp);
862 return NULL;
af49bbbe
PB
863}
864
ee0a19ec
PB
865NBDExport *nbd_export_find(const char *name)
866{
867 NBDExport *exp;
868 QTAILQ_FOREACH(exp, &exports, next) {
869 if (strcmp(name, exp->name) == 0) {
870 return exp;
871 }
872 }
873
874 return NULL;
875}
876
877void nbd_export_set_name(NBDExport *exp, const char *name)
878{
879 if (exp->name == name) {
880 return;
881 }
882
883 nbd_export_get(exp);
884 if (exp->name != NULL) {
885 g_free(exp->name);
886 exp->name = NULL;
887 QTAILQ_REMOVE(&exports, exp, next);
888 nbd_export_put(exp);
889 }
890 if (name != NULL) {
891 nbd_export_get(exp);
892 exp->name = g_strdup(name);
893 QTAILQ_INSERT_TAIL(&exports, exp, next);
894 }
895 nbd_export_put(exp);
896}
897
b1a75b33
EB
898void nbd_export_set_description(NBDExport *exp, const char *description)
899{
900 g_free(exp->description);
901 exp->description = g_strdup(description);
902}
903
af49bbbe
PB
904void nbd_export_close(NBDExport *exp)
905{
4b9441f6 906 NBDClient *client, *next;
2c8d9f06 907
4b9441f6
PB
908 nbd_export_get(exp);
909 QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
0c9390d9 910 client_close(client, true);
4b9441f6 911 }
125afda8 912 nbd_export_set_name(exp, NULL);
b1a75b33 913 nbd_export_set_description(exp, NULL);
4b9441f6 914 nbd_export_put(exp);
2c8d9f06
PB
915}
916
917void nbd_export_get(NBDExport *exp)
918{
919 assert(exp->refcount > 0);
920 exp->refcount++;
921}
922
923void nbd_export_put(NBDExport *exp)
924{
925 assert(exp->refcount > 0);
926 if (exp->refcount == 1) {
927 nbd_export_close(exp);
d9a73806
PB
928 }
929
2c8d9f06 930 if (--exp->refcount == 0) {
ee0a19ec 931 assert(exp->name == NULL);
b1a75b33 932 assert(exp->description == NULL);
ee0a19ec 933
0ddf08db
PB
934 if (exp->close) {
935 exp->close(exp);
936 }
937
d6268348 938 if (exp->blk) {
cd7fca95
KW
939 if (exp->eject_notifier_blk) {
940 notifier_remove(&exp->eject_notifier);
941 blk_unref(exp->eject_notifier_blk);
942 }
d6268348
WC
943 blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
944 blk_aio_detach, exp);
945 blk_unref(exp->blk);
946 exp->blk = NULL;
947 }
948
2c8d9f06
PB
949 g_free(exp);
950 }
af49bbbe
PB
951}
952
e140177d 953BlockBackend *nbd_export_get_blockdev(NBDExport *exp)
125afda8 954{
aadf99a7 955 return exp->blk;
125afda8
PB
956}
957
ee0a19ec
PB
958void nbd_export_close_all(void)
959{
960 NBDExport *exp, *next;
961
962 QTAILQ_FOREACH_SAFE(exp, &exports, next, next) {
963 nbd_export_close(exp);
ee0a19ec
PB
964 }
965}
966
a0dc63a6 967static int nbd_co_send_reply(NBDRequestData *req, NBDReply *reply, int len)
22045592 968{
72deddc5 969 NBDClient *client = req->client;
572b97e7 970 int rc;
22045592 971
1c778ef7 972 g_assert(qemu_in_coroutine());
262db388 973 qemu_co_mutex_lock(&client->send_lock);
262db388
PB
974 client->send_coroutine = qemu_coroutine_self();
975
22045592 976 if (!len) {
1c778ef7 977 rc = nbd_send_reply(client->ioc, reply);
22045592 978 } else {
1c778ef7
DB
979 qio_channel_set_cork(client->ioc, true);
980 rc = nbd_send_reply(client->ioc, reply);
572b97e7
VSO
981 if (rc == 0) {
982 rc = nbd_write(client->ioc, req->data, len, NULL);
983 if (rc < 0) {
185b4338 984 rc = -EIO;
22045592
PB
985 }
986 }
1c778ef7 987 qio_channel_set_cork(client->ioc, false);
22045592 988 }
262db388
PB
989
990 client->send_coroutine = NULL;
262db388 991 qemu_co_mutex_unlock(&client->send_lock);
22045592
PB
992 return rc;
993}
994
2a6e128b
VSO
995/* nbd_co_receive_request
996 * Collect a client request. Return 0 if request looks valid, -EIO to drop
997 * connection right away, and any other negative value to report an error to
998 * the client (although the caller may still need to disconnect after reporting
999 * the error).
1000 */
a0dc63a6 1001static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request)
a030b347 1002{
72deddc5 1003 NBDClient *client = req->client;
a030b347 1004
1c778ef7 1005 g_assert(qemu_in_coroutine());
ff82911c 1006 assert(client->recv_coroutine == qemu_coroutine_self());
ee898b87
VSO
1007 if (nbd_receive_request(client->ioc, request) < 0) {
1008 return -EIO;
a030b347
PB
1009 }
1010
29b6c3b3
EB
1011 TRACE("Decoding type");
1012
b626b51a 1013 if (request->type != NBD_CMD_WRITE) {
29b6c3b3
EB
1014 /* No payload, we are ready to read the next request. */
1015 req->complete = true;
1016 }
1017
b626b51a 1018 if (request->type == NBD_CMD_DISC) {
29b6c3b3
EB
1019 /* Special case: we're going to disconnect without a reply,
1020 * whether or not flags, from, or len are bogus */
1021 TRACE("Request type is DISCONNECT");
ee898b87 1022 return -EIO;
29b6c3b3
EB
1023 }
1024
1025 /* Check for sanity in the parameters, part 1. Defer as many
1026 * checks as possible until after reading any NBD_CMD_WRITE
1027 * payload, so we can try and keep the connection alive. */
a030b347 1028 if ((request->from + request->len) < request->from) {
29b6c3b3 1029 LOG("integer overflow detected, you're probably being attacked");
ee898b87 1030 return -EINVAL;
a030b347
PB
1031 }
1032
b626b51a 1033 if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE) {
eb38c3b6 1034 if (request->len > NBD_MAX_BUFFER_SIZE) {
2cb34749 1035 LOG("len (%" PRIu32" ) is larger than max len (%u)",
eb38c3b6 1036 request->len, NBD_MAX_BUFFER_SIZE);
ee898b87 1037 return -EINVAL;
eb38c3b6
PB
1038 }
1039
f1c17521
PB
1040 req->data = blk_try_blockalign(client->exp->blk, request->len);
1041 if (req->data == NULL) {
ee898b87 1042 return -ENOMEM;
f1c17521 1043 }
2d821488 1044 }
b626b51a 1045 if (request->type == NBD_CMD_WRITE) {
2cb34749 1046 TRACE("Reading %" PRIu32 " byte(s)", request->len);
a030b347 1047
d1fdf257 1048 if (nbd_read(client->ioc, req->data, request->len, NULL) < 0) {
a030b347 1049 LOG("reading from socket failed");
ee898b87 1050 return -EIO;
a030b347 1051 }
29b6c3b3 1052 req->complete = true;
a030b347 1053 }
29b6c3b3
EB
1054
1055 /* Sanity checks, part 2. */
1056 if (request->from + request->len > client->exp->size) {
1057 LOG("operation past EOF; From: %" PRIu64 ", Len: %" PRIu32
1058 ", Size: %" PRIu64, request->from, request->len,
1059 (uint64_t)client->exp->size);
ee898b87 1060 return request->type == NBD_CMD_WRITE ? -ENOSPC : -EINVAL;
29b6c3b3 1061 }
1f4d6d18 1062 if (request->flags & ~(NBD_CMD_FLAG_FUA | NBD_CMD_FLAG_NO_HOLE)) {
b626b51a 1063 LOG("unsupported flags (got 0x%x)", request->flags);
ee898b87 1064 return -EINVAL;
ab7c548e 1065 }
1f4d6d18
EB
1066 if (request->type != NBD_CMD_WRITE_ZEROES &&
1067 (request->flags & NBD_CMD_FLAG_NO_HOLE)) {
1068 LOG("unexpected flags (got 0x%x)", request->flags);
ee898b87 1069 return -EINVAL;
1f4d6d18 1070 }
29b6c3b3 1071
ee898b87 1072 return 0;
a030b347
PB
1073}
1074
ff82911c
PB
1075/* Owns a reference to the NBDClient passed as opaque. */
1076static coroutine_fn void nbd_trip(void *opaque)
75818250 1077{
262db388 1078 NBDClient *client = opaque;
1743b515 1079 NBDExport *exp = client->exp;
315f78ab 1080 NBDRequestData *req;
ff82911c 1081 NBDRequest request = { 0 }; /* GCC thinks it can be used uninitialized */
ed2dd912 1082 NBDReply reply;
a0dc63a6 1083 int ret;
a0c30369 1084 int flags;
b2e3d87f
NT
1085
1086 TRACE("Reading request.");
ff2b68aa 1087 if (client->closing) {
ff82911c 1088 nbd_client_put(client);
ff2b68aa
PB
1089 return;
1090 }
b2e3d87f 1091
ff2b68aa 1092 req = nbd_request_get(client);
262db388 1093 ret = nbd_co_receive_request(req, &request);
ee898b87
VSO
1094 client->recv_coroutine = NULL;
1095 nbd_client_receive_next_request(client);
a030b347 1096 if (ret == -EIO) {
d9a73806 1097 goto out;
a030b347 1098 }
b2e3d87f 1099
fae69416
PB
1100 reply.handle = request.handle;
1101 reply.error = 0;
1102
a030b347
PB
1103 if (ret < 0) {
1104 reply.error = -ret;
1105 goto error_reply;
b2e3d87f 1106 }
b2e3d87f 1107
d6268348
WC
1108 if (client->closing) {
1109 /*
1110 * The client may be closed when we are blocked in
1111 * nbd_co_receive_request()
1112 */
1113 goto done;
1114 }
1115
b626b51a 1116 switch (request.type) {
b2e3d87f
NT
1117 case NBD_CMD_READ:
1118 TRACE("Request type is READ");
1119
b626b51a
EB
1120 /* XXX: NBD Protocol only documents use of FUA with WRITE */
1121 if (request.flags & NBD_CMD_FLAG_FUA) {
aadf99a7 1122 ret = blk_co_flush(exp->blk);
e25ceb76
PB
1123 if (ret < 0) {
1124 LOG("flush failed");
1125 reply.error = -ret;
1126 goto error_reply;
1127 }
1128 }
1129
df7b97ff
EB
1130 ret = blk_pread(exp->blk, request.from + exp->dev_offset,
1131 req->data, request.len);
adcf6302 1132 if (ret < 0) {
b2e3d87f 1133 LOG("reading from file failed");
adcf6302 1134 reply.error = -ret;
fae69416 1135 goto error_reply;
b2e3d87f 1136 }
b2e3d87f 1137
2cb34749 1138 TRACE("Read %" PRIu32" byte(s)", request.len);
262db388 1139 if (nbd_co_send_reply(req, &reply, request.len) < 0)
d9a73806 1140 goto out;
b2e3d87f
NT
1141 break;
1142 case NBD_CMD_WRITE:
1143 TRACE("Request type is WRITE");
1144
af49bbbe 1145 if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
b2e3d87f 1146 TRACE("Server is read-only, return error");
fae69416
PB
1147 reply.error = EROFS;
1148 goto error_reply;
1149 }
1150
1151 TRACE("Writing to device");
1152
a0c30369 1153 flags = 0;
b626b51a 1154 if (request.flags & NBD_CMD_FLAG_FUA) {
a0c30369
EB
1155 flags |= BDRV_REQ_FUA;
1156 }
df7b97ff 1157 ret = blk_pwrite(exp->blk, request.from + exp->dev_offset,
a0c30369 1158 req->data, request.len, flags);
fae69416
PB
1159 if (ret < 0) {
1160 LOG("writing to file failed");
1161 reply.error = -ret;
1162 goto error_reply;
1163 }
b2e3d87f 1164
1f4d6d18
EB
1165 if (nbd_co_send_reply(req, &reply, 0) < 0) {
1166 goto out;
1167 }
1168 break;
1169
1170 case NBD_CMD_WRITE_ZEROES:
1171 TRACE("Request type is WRITE_ZEROES");
1172
1173 if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
1174 TRACE("Server is read-only, return error");
1175 reply.error = EROFS;
1176 goto error_reply;
1177 }
1178
1179 TRACE("Writing to device");
1180
1181 flags = 0;
1182 if (request.flags & NBD_CMD_FLAG_FUA) {
1183 flags |= BDRV_REQ_FUA;
1184 }
1185 if (!(request.flags & NBD_CMD_FLAG_NO_HOLE)) {
1186 flags |= BDRV_REQ_MAY_UNMAP;
1187 }
1188 ret = blk_pwrite_zeroes(exp->blk, request.from + exp->dev_offset,
1189 request.len, flags);
1190 if (ret < 0) {
1191 LOG("writing to file failed");
1192 reply.error = -ret;
1193 goto error_reply;
1194 }
1195
fc19f8a0 1196 if (nbd_co_send_reply(req, &reply, 0) < 0) {
d9a73806 1197 goto out;
fc19f8a0 1198 }
b2e3d87f 1199 break;
29b6c3b3 1200
b2e3d87f 1201 case NBD_CMD_DISC:
29b6c3b3
EB
1202 /* unreachable, thanks to special case in nbd_co_receive_request() */
1203 abort();
1204
1486d04a
PB
1205 case NBD_CMD_FLUSH:
1206 TRACE("Request type is FLUSH");
1207
aadf99a7 1208 ret = blk_co_flush(exp->blk);
1486d04a
PB
1209 if (ret < 0) {
1210 LOG("flush failed");
1211 reply.error = -ret;
1212 }
fc19f8a0 1213 if (nbd_co_send_reply(req, &reply, 0) < 0) {
d9a73806 1214 goto out;
fc19f8a0 1215 }
7a706633
PB
1216 break;
1217 case NBD_CMD_TRIM:
1218 TRACE("Request type is TRIM");
1c6c4bb7
EB
1219 ret = blk_co_pdiscard(exp->blk, request.from + exp->dev_offset,
1220 request.len);
1221 if (ret < 0) {
1222 LOG("discard failed");
1223 reply.error = -ret;
7a706633 1224 }
fc19f8a0 1225 if (nbd_co_send_reply(req, &reply, 0) < 0) {
d9a73806 1226 goto out;
fc19f8a0 1227 }
1486d04a 1228 break;
b2e3d87f 1229 default:
2cb34749 1230 LOG("invalid request type (%" PRIu32 ") received", request.type);
8b2f0abf 1231 reply.error = EINVAL;
fae69416 1232 error_reply:
29b6c3b3
EB
1233 /* We must disconnect after NBD_CMD_WRITE if we did not
1234 * read the payload.
1235 */
1236 if (nbd_co_send_reply(req, &reply, 0) < 0 || !req->complete) {
d9a73806 1237 goto out;
fc19f8a0 1238 }
fae69416 1239 break;
b2e3d87f
NT
1240 }
1241
1242 TRACE("Request/Reply complete");
1243
7fe7b68b 1244done:
262db388 1245 nbd_request_put(req);
ff82911c 1246 nbd_client_put(client);
262db388
PB
1247 return;
1248
d9a73806 1249out:
72deddc5 1250 nbd_request_put(req);
0c9390d9 1251 client_close(client, true);
ff82911c 1252 nbd_client_put(client);
7a5ca864 1253}
af49bbbe 1254
ff82911c 1255static void nbd_client_receive_next_request(NBDClient *client)
958c717d 1256{
ff82911c
PB
1257 if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS) {
1258 nbd_client_get(client);
1259 client->recv_coroutine = qemu_coroutine_create(nbd_trip, client);
1260 aio_co_schedule(client->exp->ctx, client->recv_coroutine);
958c717d
HR
1261 }
1262}
1263
1a6245a5
FZ
1264static coroutine_fn void nbd_co_client_start(void *opaque)
1265{
c84087f2 1266 NBDClient *client = opaque;
1a6245a5
FZ
1267 NBDExport *exp = client->exp;
1268
1269 if (exp) {
1270 nbd_export_get(exp);
df8ad9f1 1271 QTAILQ_INSERT_TAIL(&exp->clients, client, next);
1a6245a5 1272 }
df8ad9f1
EB
1273 qemu_co_mutex_init(&client->send_lock);
1274
c84087f2 1275 if (nbd_negotiate(client)) {
0c9390d9 1276 client_close(client, false);
c84087f2 1277 return;
1a6245a5 1278 }
ff82911c
PB
1279
1280 nbd_client_receive_next_request(client);
1a6245a5
FZ
1281}
1282
0c9390d9
EB
1283/*
1284 * Create a new client listener on the given export @exp, using the
1285 * given channel @sioc. Begin servicing it in a coroutine. When the
1286 * connection closes, call @close_fn with an indication of whether the
1287 * client completed negotiation.
1288 */
1c778ef7
DB
1289void nbd_client_new(NBDExport *exp,
1290 QIOChannelSocket *sioc,
f95910fe
DB
1291 QCryptoTLSCreds *tlscreds,
1292 const char *tlsaclname,
0c9390d9 1293 void (*close_fn)(NBDClient *, bool))
af49bbbe 1294{
1743b515 1295 NBDClient *client;
c84087f2 1296 Coroutine *co;
1a6245a5 1297
1743b515
PB
1298 client = g_malloc0(sizeof(NBDClient));
1299 client->refcount = 1;
1300 client->exp = exp;
f95910fe
DB
1301 client->tlscreds = tlscreds;
1302 if (tlscreds) {
1303 object_ref(OBJECT(client->tlscreds));
1304 }
1305 client->tlsaclname = g_strdup(tlsaclname);
1c778ef7
DB
1306 client->sioc = sioc;
1307 object_ref(OBJECT(client->sioc));
1308 client->ioc = QIO_CHANNEL(sioc);
1309 object_ref(OBJECT(client->ioc));
0c9390d9 1310 client->close_fn = close_fn;
2c8d9f06 1311
c84087f2
VSO
1312 co = qemu_coroutine_create(nbd_co_client_start, client);
1313 qemu_coroutine_enter(co);
af49bbbe 1314}