1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21#include "qapi/error.h"
22#include "qemu/queue.h"
23#include "trace.h"
24#include "nbd-internal.h"
25#include "qemu/units.h"
26
27#define NBD_META_ID_BASE_ALLOCATION 0
28#define NBD_META_ID_DIRTY_BITMAP 1
29
30
31
32
33
34
35
36#define NBD_MAX_BLOCK_STATUS_EXTENTS (1 * MiB / 8)
37
38static int system_errno_to_nbd_errno(int err)
39{
40 switch (err) {
41 case 0:
42 return NBD_SUCCESS;
43 case EPERM:
44 case EROFS:
45 return NBD_EPERM;
46 case EIO:
47 return NBD_EIO;
48 case ENOMEM:
49 return NBD_ENOMEM;
50#ifdef EDQUOT
51 case EDQUOT:
52#endif
53 case EFBIG:
54 case ENOSPC:
55 return NBD_ENOSPC;
56 case EOVERFLOW:
57 return NBD_EOVERFLOW;
58 case ENOTSUP:
59#if ENOTSUP != EOPNOTSUPP
60 case EOPNOTSUPP:
61#endif
62 return NBD_ENOTSUP;
63 case ESHUTDOWN:
64 return NBD_ESHUTDOWN;
65 case EINVAL:
66 default:
67 return NBD_EINVAL;
68 }
69}
70
71
72
73typedef struct NBDRequestData NBDRequestData;
74
75struct NBDRequestData {
76 QSIMPLEQ_ENTRY(NBDRequestData) entry;
77 NBDClient *client;
78 uint8_t *data;
79 bool complete;
80};
81
82struct NBDExport {
83 int refcount;
84 void (*close)(NBDExport *exp);
85
86 BlockBackend *blk;
87 char *name;
88 char *description;
89 uint64_t dev_offset;
90 uint64_t size;
91 uint16_t nbdflags;
92 QTAILQ_HEAD(, NBDClient) clients;
93 QTAILQ_ENTRY(NBDExport) next;
94
95 AioContext *ctx;
96
97 BlockBackend *eject_notifier_blk;
98 Notifier eject_notifier;
99
100 BdrvDirtyBitmap *export_bitmap;
101 char *export_bitmap_context;
102};
103
104static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
105
106
107
108
109typedef struct NBDExportMetaContexts {
110 NBDExport *exp;
111 bool valid;
112
113 bool base_allocation;
114 bool bitmap;
115} NBDExportMetaContexts;
116
117struct NBDClient {
118 int refcount;
119 void (*close_fn)(NBDClient *client, bool negotiated);
120
121 NBDExport *exp;
122 QCryptoTLSCreds *tlscreds;
123 char *tlsauthz;
124 QIOChannelSocket *sioc;
125 QIOChannel *ioc;
126
127 Coroutine *recv_coroutine;
128
129 CoMutex send_lock;
130 Coroutine *send_coroutine;
131
132 QTAILQ_ENTRY(NBDClient) next;
133 int nb_requests;
134 bool closing;
135
136 uint32_t check_align;
137
138 bool structured_reply;
139 NBDExportMetaContexts export_meta;
140
141 uint32_t opt;
142 uint32_t optlen;
143
144};
145
146static void nbd_client_receive_next_request(NBDClient *client);
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175static inline void set_be_option_rep(NBDOptionReply *rep, uint32_t option,
176 uint32_t type, uint32_t length)
177{
178 stq_be_p(&rep->magic, NBD_REP_MAGIC);
179 stl_be_p(&rep->option, option);
180 stl_be_p(&rep->type, type);
181 stl_be_p(&rep->length, length);
182}
183
184
185
186static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
187 uint32_t len, Error **errp)
188{
189 NBDOptionReply rep;
190
191 trace_nbd_negotiate_send_rep_len(client->opt, nbd_opt_lookup(client->opt),
192 type, nbd_rep_lookup(type), len);
193
194 assert(len < NBD_MAX_BUFFER_SIZE);
195
196 set_be_option_rep(&rep, client->opt, type, len);
197 return nbd_write(client->ioc, &rep, sizeof(rep), errp);
198}
199
200
201
202static int nbd_negotiate_send_rep(NBDClient *client, uint32_t type,
203 Error **errp)
204{
205 return nbd_negotiate_send_rep_len(client, type, 0, errp);
206}
207
208
209
210static int GCC_FMT_ATTR(4, 0)
211nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
212 Error **errp, const char *fmt, va_list va)
213{
214 g_autofree char *msg = NULL;
215 int ret;
216 size_t len;
217
218 msg = g_strdup_vprintf(fmt, va);
219 len = strlen(msg);
220 assert(len < 4096);
221 trace_nbd_negotiate_send_rep_err(msg);
222 ret = nbd_negotiate_send_rep_len(client, type, len, errp);
223 if (ret < 0) {
224 return ret;
225 }
226 if (nbd_write(client->ioc, msg, len, errp) < 0) {
227 error_prepend(errp, "write failed (error message): ");
228 return -EIO;
229 }
230
231 return 0;
232}
233
234
235
236static int GCC_FMT_ATTR(4, 5)
237nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
238 Error **errp, const char *fmt, ...)
239{
240 va_list va;
241 int ret;
242
243 va_start(va, fmt);
244 ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
245 va_end(va);
246 return ret;
247}
248
249
250
251
252static int GCC_FMT_ATTR(4, 0)
253nbd_opt_vdrop(NBDClient *client, uint32_t type, Error **errp,
254 const char *fmt, va_list va)
255{
256 int ret = nbd_drop(client->ioc, client->optlen, errp);
257
258 client->optlen = 0;
259 if (!ret) {
260 ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
261 }
262 return ret;
263}
264
265static int GCC_FMT_ATTR(4, 5)
266nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp,
267 const char *fmt, ...)
268{
269 int ret;
270 va_list va;
271
272 va_start(va, fmt);
273 ret = nbd_opt_vdrop(client, type, errp, fmt, va);
274 va_end(va);
275
276 return ret;
277}
278
279static int GCC_FMT_ATTR(3, 4)
280nbd_opt_invalid(NBDClient *client, Error **errp, const char *fmt, ...)
281{
282 int ret;
283 va_list va;
284
285 va_start(va, fmt);
286 ret = nbd_opt_vdrop(client, NBD_REP_ERR_INVALID, errp, fmt, va);
287 va_end(va);
288
289 return ret;
290}
291
292
293
294
295static int nbd_opt_read(NBDClient *client, void *buffer, size_t size,
296 Error **errp)
297{
298 if (size > client->optlen) {
299 return nbd_opt_invalid(client, errp,
300 "Inconsistent lengths in option %s",
301 nbd_opt_lookup(client->opt));
302 }
303 client->optlen -= size;
304 return qio_channel_read_all(client->ioc, buffer, size, errp) < 0 ? -EIO : 1;
305}
306
307
308
309
310static int nbd_opt_skip(NBDClient *client, size_t size, Error **errp)
311{
312 if (size > client->optlen) {
313 return nbd_opt_invalid(client, errp,
314 "Inconsistent lengths in option %s",
315 nbd_opt_lookup(client->opt));
316 }
317 client->optlen -= size;
318 return nbd_drop(client->ioc, size, errp) < 0 ? -EIO : 1;
319}
320
321
322
323
324
325
326
327
328
329
330
331
332
333static int nbd_opt_read_name(NBDClient *client, char **name, uint32_t *length,
334 Error **errp)
335{
336 int ret;
337 uint32_t len;
338 g_autofree char *local_name = NULL;
339
340 *name = NULL;
341 ret = nbd_opt_read(client, &len, sizeof(len), errp);
342 if (ret <= 0) {
343 return ret;
344 }
345 len = cpu_to_be32(len);
346
347 if (len > NBD_MAX_STRING_SIZE) {
348 return nbd_opt_invalid(client, errp,
349 "Invalid name length: %" PRIu32, len);
350 }
351
352 local_name = g_malloc(len + 1);
353 ret = nbd_opt_read(client, local_name, len, errp);
354 if (ret <= 0) {
355 return ret;
356 }
357 local_name[len] = '\0';
358
359 if (length) {
360 *length = len;
361 }
362 *name = g_steal_pointer(&local_name);
363
364 return 1;
365}
366
367
368
369static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
370 Error **errp)
371{
372 size_t name_len, desc_len;
373 uint32_t len;
374 const char *name = exp->name ? exp->name : "";
375 const char *desc = exp->description ? exp->description : "";
376 QIOChannel *ioc = client->ioc;
377 int ret;
378
379 trace_nbd_negotiate_send_rep_list(name, desc);
380 name_len = strlen(name);
381 desc_len = strlen(desc);
382 assert(name_len <= NBD_MAX_STRING_SIZE && desc_len <= NBD_MAX_STRING_SIZE);
383 len = name_len + desc_len + sizeof(len);
384 ret = nbd_negotiate_send_rep_len(client, NBD_REP_SERVER, len, errp);
385 if (ret < 0) {
386 return ret;
387 }
388
389 len = cpu_to_be32(name_len);
390 if (nbd_write(ioc, &len, sizeof(len), errp) < 0) {
391 error_prepend(errp, "write failed (name length): ");
392 return -EINVAL;
393 }
394
395 if (nbd_write(ioc, name, name_len, errp) < 0) {
396 error_prepend(errp, "write failed (name buffer): ");
397 return -EINVAL;
398 }
399
400 if (nbd_write(ioc, desc, desc_len, errp) < 0) {
401 error_prepend(errp, "write failed (description buffer): ");
402 return -EINVAL;
403 }
404
405 return 0;
406}
407
408
409
410static int nbd_negotiate_handle_list(NBDClient *client, Error **errp)
411{
412 NBDExport *exp;
413 assert(client->opt == NBD_OPT_LIST);
414
415
416 QTAILQ_FOREACH(exp, &exports, next) {
417 if (nbd_negotiate_send_rep_list(client, exp, errp)) {
418 return -EINVAL;
419 }
420 }
421
422 return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
423}
424
425static void nbd_check_meta_export(NBDClient *client)
426{
427 client->export_meta.valid &= client->exp == client->export_meta.exp;
428}
429
430
431
432static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
433 Error **errp)
434{
435 g_autofree char *name = NULL;
436 char buf[NBD_REPLY_EXPORT_NAME_SIZE] = "";
437 size_t len;
438 int ret;
439 uint16_t myflags;
440
441
442
443
444
445
446
447
448 trace_nbd_negotiate_handle_export_name();
449 if (client->optlen > NBD_MAX_STRING_SIZE) {
450 error_setg(errp, "Bad length received");
451 return -EINVAL;
452 }
453 name = g_malloc(client->optlen + 1);
454 if (nbd_read(client->ioc, name, client->optlen, "export name", errp) < 0) {
455 return -EIO;
456 }
457 name[client->optlen] = '\0';
458 client->optlen = 0;
459
460 trace_nbd_negotiate_handle_export_name_request(name);
461
462 client->exp = nbd_export_find(name);
463 if (!client->exp) {
464 error_setg(errp, "export not found");
465 return -EINVAL;
466 }
467
468 myflags = client->exp->nbdflags;
469 if (client->structured_reply) {
470 myflags |= NBD_FLAG_SEND_DF;
471 }
472 trace_nbd_negotiate_new_style_size_flags(client->exp->size, myflags);
473 stq_be_p(buf, client->exp->size);
474 stw_be_p(buf + 8, myflags);
475 len = no_zeroes ? 10 : sizeof(buf);
476 ret = nbd_write(client->ioc, buf, len, errp);
477 if (ret < 0) {
478 error_prepend(errp, "write failed: ");
479 return ret;
480 }
481
482 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
483 nbd_export_get(client->exp);
484 nbd_check_meta_export(client);
485
486 return 0;
487}
488
489
490
491
492static int nbd_negotiate_send_info(NBDClient *client,
493 uint16_t info, uint32_t length, void *buf,
494 Error **errp)
495{
496 int rc;
497
498 trace_nbd_negotiate_send_info(info, nbd_info_lookup(info), length);
499 rc = nbd_negotiate_send_rep_len(client, NBD_REP_INFO,
500 sizeof(info) + length, errp);
501 if (rc < 0) {
502 return rc;
503 }
504 info = cpu_to_be16(info);
505 if (nbd_write(client->ioc, &info, sizeof(info), errp) < 0) {
506 return -EIO;
507 }
508 if (nbd_write(client->ioc, buf, length, errp) < 0) {
509 return -EIO;
510 }
511 return 0;
512}
513
514
515
516
517
518
519
520
521static int nbd_reject_length(NBDClient *client, bool fatal, Error **errp)
522{
523 int ret;
524
525 assert(client->optlen);
526 ret = nbd_opt_invalid(client, errp, "option '%s' has unexpected length",
527 nbd_opt_lookup(client->opt));
528 if (fatal && !ret) {
529 error_setg(errp, "option '%s' has unexpected length",
530 nbd_opt_lookup(client->opt));
531 return -EINVAL;
532 }
533 return ret;
534}
535
536
537
538
539static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
540{
541 int rc;
542 g_autofree char *name = NULL;
543 NBDExport *exp;
544 uint16_t requests;
545 uint16_t request;
546 uint32_t namelen;
547 bool sendname = false;
548 bool blocksize = false;
549 uint32_t sizes[3];
550 char buf[sizeof(uint64_t) + sizeof(uint16_t)];
551 uint32_t check_align = 0;
552 uint16_t myflags;
553
554
555
556
557
558
559
560 rc = nbd_opt_read_name(client, &name, &namelen, errp);
561 if (rc <= 0) {
562 return rc;
563 }
564 trace_nbd_negotiate_handle_export_name_request(name);
565
566 rc = nbd_opt_read(client, &requests, sizeof(requests), errp);
567 if (rc <= 0) {
568 return rc;
569 }
570 requests = be16_to_cpu(requests);
571 trace_nbd_negotiate_handle_info_requests(requests);
572 while (requests--) {
573 rc = nbd_opt_read(client, &request, sizeof(request), errp);
574 if (rc <= 0) {
575 return rc;
576 }
577 request = be16_to_cpu(request);
578 trace_nbd_negotiate_handle_info_request(request,
579 nbd_info_lookup(request));
580
581
582
583 switch (request) {
584 case NBD_INFO_NAME:
585 sendname = true;
586 break;
587 case NBD_INFO_BLOCK_SIZE:
588 blocksize = true;
589 break;
590 }
591 }
592 if (client->optlen) {
593 return nbd_reject_length(client, false, errp);
594 }
595
596 exp = nbd_export_find(name);
597 if (!exp) {
598 return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN,
599 errp, "export '%s' not present",
600 name);
601 }
602
603
604 if (sendname) {
605 rc = nbd_negotiate_send_info(client, NBD_INFO_NAME, namelen, name,
606 errp);
607 if (rc < 0) {
608 return rc;
609 }
610 }
611
612
613
614 if (exp->description) {
615 size_t len = strlen(exp->description);
616
617 assert(len <= NBD_MAX_STRING_SIZE);
618 rc = nbd_negotiate_send_info(client, NBD_INFO_DESCRIPTION,
619 len, exp->description, errp);
620 if (rc < 0) {
621 return rc;
622 }
623 }
624
625
626
627
628
629 if (client->opt == NBD_OPT_INFO || blocksize) {
630 check_align = sizes[0] = blk_get_request_alignment(exp->blk);
631 } else {
632 sizes[0] = 1;
633 }
634 assert(sizes[0] <= NBD_MAX_BUFFER_SIZE);
635
636
637 sizes[1] = MAX(4096, sizes[0]);
638
639 sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE);
640 trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]);
641 sizes[0] = cpu_to_be32(sizes[0]);
642 sizes[1] = cpu_to_be32(sizes[1]);
643 sizes[2] = cpu_to_be32(sizes[2]);
644 rc = nbd_negotiate_send_info(client, NBD_INFO_BLOCK_SIZE,
645 sizeof(sizes), sizes, errp);
646 if (rc < 0) {
647 return rc;
648 }
649
650
651 myflags = exp->nbdflags;
652 if (client->structured_reply) {
653 myflags |= NBD_FLAG_SEND_DF;
654 }
655 trace_nbd_negotiate_new_style_size_flags(exp->size, myflags);
656 stq_be_p(buf, exp->size);
657 stw_be_p(buf + 8, myflags);
658 rc = nbd_negotiate_send_info(client, NBD_INFO_EXPORT,
659 sizeof(buf), buf, errp);
660 if (rc < 0) {
661 return rc;
662 }
663
664
665
666
667
668
669
670 if (client->opt == NBD_OPT_INFO && !blocksize &&
671 blk_get_request_alignment(exp->blk) > 1) {
672 return nbd_negotiate_send_rep_err(client,
673 NBD_REP_ERR_BLOCK_SIZE_REQD,
674 errp,
675 "request NBD_INFO_BLOCK_SIZE to "
676 "use this export");
677 }
678
679
680 rc = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
681 if (rc < 0) {
682 return rc;
683 }
684
685 if (client->opt == NBD_OPT_GO) {
686 client->exp = exp;
687 client->check_align = check_align;
688 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
689 nbd_export_get(client->exp);
690 nbd_check_meta_export(client);
691 rc = 1;
692 }
693 return rc;
694}
695
696
697
698
699static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
700 Error **errp)
701{
702 QIOChannel *ioc;
703 QIOChannelTLS *tioc;
704 struct NBDTLSHandshakeData data = { 0 };
705
706 assert(client->opt == NBD_OPT_STARTTLS);
707
708 trace_nbd_negotiate_handle_starttls();
709 ioc = client->ioc;
710
711 if (nbd_negotiate_send_rep(client, NBD_REP_ACK, errp) < 0) {
712 return NULL;
713 }
714
715 tioc = qio_channel_tls_new_server(ioc,
716 client->tlscreds,
717 client->tlsauthz,
718 errp);
719 if (!tioc) {
720 return NULL;
721 }
722
723 qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
724 trace_nbd_negotiate_handle_starttls_handshake();
725 data.loop = g_main_loop_new(g_main_context_default(), FALSE);
726 qio_channel_tls_handshake(tioc,
727 nbd_tls_handshake,
728 &data,
729 NULL,
730 NULL);
731
732 if (!data.complete) {
733 g_main_loop_run(data.loop);
734 }
735 g_main_loop_unref(data.loop);
736 if (data.error) {
737 object_unref(OBJECT(tioc));
738 error_propagate(errp, data.error);
739 return NULL;
740 }
741
742 return QIO_CHANNEL(tioc);
743}
744
745
746
747
748
749
750
751static int nbd_negotiate_send_meta_context(NBDClient *client,
752 const char *context,
753 uint32_t context_id,
754 Error **errp)
755{
756 NBDOptionReplyMetaContext opt;
757 struct iovec iov[] = {
758 {.iov_base = &opt, .iov_len = sizeof(opt)},
759 {.iov_base = (void *)context, .iov_len = strlen(context)}
760 };
761
762 assert(iov[1].iov_len <= NBD_MAX_STRING_SIZE);
763 if (client->opt == NBD_OPT_LIST_META_CONTEXT) {
764 context_id = 0;
765 }
766
767 trace_nbd_negotiate_meta_query_reply(context, context_id);
768 set_be_option_rep(&opt.h, client->opt, NBD_REP_META_CONTEXT,
769 sizeof(opt) - sizeof(opt.h) + iov[1].iov_len);
770 stl_be_p(&opt.context_id, context_id);
771
772 return qio_channel_writev_all(client->ioc, iov, 2, errp) < 0 ? -EIO : 0;
773}
774
775
776
777
778
779
780
781
782
783
784static int nbd_meta_pattern(NBDClient *client, const char *pattern, bool *match,
785 Error **errp)
786{
787 int ret;
788 char *query;
789 size_t len = strlen(pattern);
790
791 assert(len);
792
793 query = g_malloc(len);
794 ret = nbd_opt_read(client, query, len, errp);
795 if (ret <= 0) {
796 g_free(query);
797 return ret;
798 }
799
800 if (strncmp(query, pattern, len) == 0) {
801 trace_nbd_negotiate_meta_query_parse(pattern);
802 *match = true;
803 } else {
804 trace_nbd_negotiate_meta_query_skip("pattern not matched");
805 }
806 g_free(query);
807
808 return 1;
809}
810
811
812
813
814
815
816
817
818
819
820
821static int nbd_meta_empty_or_pattern(NBDClient *client, const char *pattern,
822 uint32_t len, bool *match, Error **errp)
823{
824 if (len == 0) {
825 if (client->opt == NBD_OPT_LIST_META_CONTEXT) {
826 *match = true;
827 }
828 trace_nbd_negotiate_meta_query_parse("empty");
829 return 1;
830 }
831
832 if (len != strlen(pattern)) {
833 trace_nbd_negotiate_meta_query_skip("different lengths");
834 return nbd_opt_skip(client, len, errp);
835 }
836
837 return nbd_meta_pattern(client, pattern, match, errp);
838}
839
840
841
842
843
844
845
846
847
848
849static int nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta,
850 uint32_t len, Error **errp)
851{
852 return nbd_meta_empty_or_pattern(client, "allocation", len,
853 &meta->base_allocation, errp);
854}
855
856
857
858
859
860
861
862
863
864static int nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta,
865 uint32_t len, Error **errp)
866{
867 bool dirty_bitmap = false;
868 size_t dirty_bitmap_len = strlen("dirty-bitmap:");
869 int ret;
870
871 if (!meta->exp->export_bitmap) {
872 trace_nbd_negotiate_meta_query_skip("no dirty-bitmap exported");
873 return nbd_opt_skip(client, len, errp);
874 }
875
876 if (len == 0) {
877 if (client->opt == NBD_OPT_LIST_META_CONTEXT) {
878 meta->bitmap = true;
879 }
880 trace_nbd_negotiate_meta_query_parse("empty");
881 return 1;
882 }
883
884 if (len < dirty_bitmap_len) {
885 trace_nbd_negotiate_meta_query_skip("not dirty-bitmap:");
886 return nbd_opt_skip(client, len, errp);
887 }
888
889 len -= dirty_bitmap_len;
890 ret = nbd_meta_pattern(client, "dirty-bitmap:", &dirty_bitmap, errp);
891 if (ret <= 0) {
892 return ret;
893 }
894 if (!dirty_bitmap) {
895 trace_nbd_negotiate_meta_query_skip("not dirty-bitmap:");
896 return nbd_opt_skip(client, len, errp);
897 }
898
899 trace_nbd_negotiate_meta_query_parse("dirty-bitmap:");
900
901 return nbd_meta_empty_or_pattern(
902 client, meta->exp->export_bitmap_context +
903 strlen("qemu:dirty_bitmap:"), len, &meta->bitmap, errp);
904}
905
906
907
908
909
910
911
912
913
914
915
916
917
918static int nbd_negotiate_meta_query(NBDClient *client,
919 NBDExportMetaContexts *meta, Error **errp)
920{
921
922
923
924
925
926 int ret;
927 size_t ns_len = 5;
928 char ns[5];
929 uint32_t len;
930
931 ret = nbd_opt_read(client, &len, sizeof(len), errp);
932 if (ret <= 0) {
933 return ret;
934 }
935 len = cpu_to_be32(len);
936
937 if (len > NBD_MAX_STRING_SIZE) {
938 trace_nbd_negotiate_meta_query_skip("length too long");
939 return nbd_opt_skip(client, len, errp);
940 }
941 if (len < ns_len) {
942 trace_nbd_negotiate_meta_query_skip("length too short");
943 return nbd_opt_skip(client, len, errp);
944 }
945
946 len -= ns_len;
947 ret = nbd_opt_read(client, ns, ns_len, errp);
948 if (ret <= 0) {
949 return ret;
950 }
951
952 if (!strncmp(ns, "base:", ns_len)) {
953 trace_nbd_negotiate_meta_query_parse("base:");
954 return nbd_meta_base_query(client, meta, len, errp);
955 } else if (!strncmp(ns, "qemu:", ns_len)) {
956 trace_nbd_negotiate_meta_query_parse("qemu:");
957 return nbd_meta_qemu_query(client, meta, len, errp);
958 }
959
960 trace_nbd_negotiate_meta_query_skip("unknown namespace");
961 return nbd_opt_skip(client, len, errp);
962}
963
964
965
966
967
968static int nbd_negotiate_meta_queries(NBDClient *client,
969 NBDExportMetaContexts *meta, Error **errp)
970{
971 int ret;
972 g_autofree char *export_name = NULL;
973 NBDExportMetaContexts local_meta;
974 uint32_t nb_queries;
975 int i;
976
977 if (!client->structured_reply) {
978 return nbd_opt_invalid(client, errp,
979 "request option '%s' when structured reply "
980 "is not negotiated",
981 nbd_opt_lookup(client->opt));
982 }
983
984 if (client->opt == NBD_OPT_LIST_META_CONTEXT) {
985
986 meta = &local_meta;
987 }
988
989 memset(meta, 0, sizeof(*meta));
990
991 ret = nbd_opt_read_name(client, &export_name, NULL, errp);
992 if (ret <= 0) {
993 return ret;
994 }
995
996 meta->exp = nbd_export_find(export_name);
997 if (meta->exp == NULL) {
998 return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp,
999 "export '%s' not present", export_name);
1000 }
1001
1002 ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), errp);
1003 if (ret <= 0) {
1004 return ret;
1005 }
1006 nb_queries = cpu_to_be32(nb_queries);
1007 trace_nbd_negotiate_meta_context(nbd_opt_lookup(client->opt),
1008 export_name, nb_queries);
1009
1010 if (client->opt == NBD_OPT_LIST_META_CONTEXT && !nb_queries) {
1011
1012 meta->base_allocation = true;
1013 meta->bitmap = !!meta->exp->export_bitmap;
1014 } else {
1015 for (i = 0; i < nb_queries; ++i) {
1016 ret = nbd_negotiate_meta_query(client, meta, errp);
1017 if (ret <= 0) {
1018 return ret;
1019 }
1020 }
1021 }
1022
1023 if (meta->base_allocation) {
1024 ret = nbd_negotiate_send_meta_context(client, "base:allocation",
1025 NBD_META_ID_BASE_ALLOCATION,
1026 errp);
1027 if (ret < 0) {
1028 return ret;
1029 }
1030 }
1031
1032 if (meta->bitmap) {
1033 ret = nbd_negotiate_send_meta_context(client,
1034 meta->exp->export_bitmap_context,
1035 NBD_META_ID_DIRTY_BITMAP,
1036 errp);
1037 if (ret < 0) {
1038 return ret;
1039 }
1040 }
1041
1042 ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
1043 if (ret == 0) {
1044 meta->valid = true;
1045 }
1046
1047 return ret;
1048}
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059static int nbd_negotiate_options(NBDClient *client, Error **errp)
1060{
1061 uint32_t flags;
1062 bool fixedNewstyle = false;
1063 bool no_zeroes = false;
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 if (nbd_read32(client->ioc, &flags, "flags", errp) < 0) {
1081 return -EIO;
1082 }
1083 trace_nbd_negotiate_options_flags(flags);
1084 if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
1085 fixedNewstyle = true;
1086 flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
1087 }
1088 if (flags & NBD_FLAG_C_NO_ZEROES) {
1089 no_zeroes = true;
1090 flags &= ~NBD_FLAG_C_NO_ZEROES;
1091 }
1092 if (flags != 0) {
1093 error_setg(errp, "Unknown client flags 0x%" PRIx32 " received", flags);
1094 return -EINVAL;
1095 }
1096
1097 while (1) {
1098 int ret;
1099 uint32_t option, length;
1100 uint64_t magic;
1101
1102 if (nbd_read64(client->ioc, &magic, "opts magic", errp) < 0) {
1103 return -EINVAL;
1104 }
1105 trace_nbd_negotiate_options_check_magic(magic);
1106 if (magic != NBD_OPTS_MAGIC) {
1107 error_setg(errp, "Bad magic received");
1108 return -EINVAL;
1109 }
1110
1111 if (nbd_read32(client->ioc, &option, "option", errp) < 0) {
1112 return -EINVAL;
1113 }
1114 client->opt = option;
1115
1116 if (nbd_read32(client->ioc, &length, "option length", errp) < 0) {
1117 return -EINVAL;
1118 }
1119 assert(!client->optlen);
1120 client->optlen = length;
1121
1122 if (length > NBD_MAX_BUFFER_SIZE) {
1123 error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
1124 length, NBD_MAX_BUFFER_SIZE);
1125 return -EINVAL;
1126 }
1127
1128 trace_nbd_negotiate_options_check_option(option,
1129 nbd_opt_lookup(option));
1130 if (client->tlscreds &&
1131 client->ioc == (QIOChannel *)client->sioc) {
1132 QIOChannel *tioc;
1133 if (!fixedNewstyle) {
1134 error_setg(errp, "Unsupported option 0x%" PRIx32, option);
1135 return -EINVAL;
1136 }
1137 switch (option) {
1138 case NBD_OPT_STARTTLS:
1139 if (length) {
1140
1141
1142 return nbd_reject_length(client, true, errp);
1143 }
1144 tioc = nbd_negotiate_handle_starttls(client, errp);
1145 if (!tioc) {
1146 return -EIO;
1147 }
1148 ret = 0;
1149 object_unref(OBJECT(client->ioc));
1150 client->ioc = QIO_CHANNEL(tioc);
1151 break;
1152
1153 case NBD_OPT_EXPORT_NAME:
1154
1155 error_setg(errp, "Option 0x%x not permitted before TLS",
1156 option);
1157 return -EINVAL;
1158
1159 default:
1160
1161
1162
1163
1164
1165
1166 ret = nbd_opt_drop(client, NBD_REP_ERR_TLS_REQD,
1167 option == NBD_OPT_ABORT ? NULL : errp,
1168 "Option 0x%" PRIx32
1169 " not permitted before TLS", option);
1170 if (option == NBD_OPT_ABORT) {
1171 return 1;
1172 }
1173 break;
1174 }
1175 } else if (fixedNewstyle) {
1176 switch (option) {
1177 case NBD_OPT_LIST:
1178 if (length) {
1179 ret = nbd_reject_length(client, false, errp);
1180 } else {
1181 ret = nbd_negotiate_handle_list(client, errp);
1182 }
1183 break;
1184
1185 case NBD_OPT_ABORT:
1186
1187
1188
1189 nbd_negotiate_send_rep(client, NBD_REP_ACK, NULL);
1190 return 1;
1191
1192 case NBD_OPT_EXPORT_NAME:
1193 return nbd_negotiate_handle_export_name(client, no_zeroes,
1194 errp);
1195
1196 case NBD_OPT_INFO:
1197 case NBD_OPT_GO:
1198 ret = nbd_negotiate_handle_info(client, errp);
1199 if (ret == 1) {
1200 assert(option == NBD_OPT_GO);
1201 return 0;
1202 }
1203 break;
1204
1205 case NBD_OPT_STARTTLS:
1206 if (length) {
1207 ret = nbd_reject_length(client, false, errp);
1208 } else if (client->tlscreds) {
1209 ret = nbd_negotiate_send_rep_err(client,
1210 NBD_REP_ERR_INVALID, errp,
1211 "TLS already enabled");
1212 } else {
1213 ret = nbd_negotiate_send_rep_err(client,
1214 NBD_REP_ERR_POLICY, errp,
1215 "TLS not configured");
1216 }
1217 break;
1218
1219 case NBD_OPT_STRUCTURED_REPLY:
1220 if (length) {
1221 ret = nbd_reject_length(client, false, errp);
1222 } else if (client->structured_reply) {
1223 ret = nbd_negotiate_send_rep_err(
1224 client, NBD_REP_ERR_INVALID, errp,
1225 "structured reply already negotiated");
1226 } else {
1227 ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
1228 client->structured_reply = true;
1229 }
1230 break;
1231
1232 case NBD_OPT_LIST_META_CONTEXT:
1233 case NBD_OPT_SET_META_CONTEXT:
1234 ret = nbd_negotiate_meta_queries(client, &client->export_meta,
1235 errp);
1236 break;
1237
1238 default:
1239 ret = nbd_opt_drop(client, NBD_REP_ERR_UNSUP, errp,
1240 "Unsupported option %" PRIu32 " (%s)",
1241 option, nbd_opt_lookup(option));
1242 break;
1243 }
1244 } else {
1245
1246
1247
1248
1249 switch (option) {
1250 case NBD_OPT_EXPORT_NAME:
1251 return nbd_negotiate_handle_export_name(client, no_zeroes,
1252 errp);
1253
1254 default:
1255 error_setg(errp, "Unsupported option %" PRIu32 " (%s)",
1256 option, nbd_opt_lookup(option));
1257 return -EINVAL;
1258 }
1259 }
1260 if (ret < 0) {
1261 return ret;
1262 }
1263 }
1264}
1265
1266
1267
1268
1269
1270
1271
1272
1273static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
1274{
1275 char buf[NBD_OLDSTYLE_NEGOTIATE_SIZE] = "";
1276 int ret;
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292 qio_channel_set_blocking(client->ioc, false, NULL);
1293
1294 trace_nbd_negotiate_begin();
1295 memcpy(buf, "NBDMAGIC", 8);
1296
1297 stq_be_p(buf + 8, NBD_OPTS_MAGIC);
1298 stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES);
1299
1300 if (nbd_write(client->ioc, buf, 18, errp) < 0) {
1301 error_prepend(errp, "write failed: ");
1302 return -EINVAL;
1303 }
1304 ret = nbd_negotiate_options(client, errp);
1305 if (ret != 0) {
1306 if (ret < 0) {
1307 error_prepend(errp, "option negotiation failed: ");
1308 }
1309 return ret;
1310 }
1311
1312
1313 if (client->exp && client->exp->ctx) {
1314 qio_channel_attach_aio_context(client->ioc, client->exp->ctx);
1315 }
1316
1317 assert(!client->optlen);
1318 trace_nbd_negotiate_success();
1319
1320 return 0;
1321}
1322
1323static int nbd_receive_request(QIOChannel *ioc, NBDRequest *request,
1324 Error **errp)
1325{
1326 uint8_t buf[NBD_REQUEST_SIZE];
1327 uint32_t magic;
1328 int ret;
1329
1330 ret = nbd_read(ioc, buf, sizeof(buf), "request", errp);
1331 if (ret < 0) {
1332 return ret;
1333 }
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344 magic = ldl_be_p(buf);
1345 request->flags = lduw_be_p(buf + 4);
1346 request->type = lduw_be_p(buf + 6);
1347 request->handle = ldq_be_p(buf + 8);
1348 request->from = ldq_be_p(buf + 16);
1349 request->len = ldl_be_p(buf + 24);
1350
1351 trace_nbd_receive_request(magic, request->flags, request->type,
1352 request->from, request->len);
1353
1354 if (magic != NBD_REQUEST_MAGIC) {
1355 error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic);
1356 return -EINVAL;
1357 }
1358 return 0;
1359}
1360
1361#define MAX_NBD_REQUESTS 16
1362
1363void nbd_client_get(NBDClient *client)
1364{
1365 client->refcount++;
1366}
1367
1368void nbd_client_put(NBDClient *client)
1369{
1370 if (--client->refcount == 0) {
1371
1372
1373
1374 assert(client->closing);
1375
1376 qio_channel_detach_aio_context(client->ioc);
1377 object_unref(OBJECT(client->sioc));
1378 object_unref(OBJECT(client->ioc));
1379 if (client->tlscreds) {
1380 object_unref(OBJECT(client->tlscreds));
1381 }
1382 g_free(client->tlsauthz);
1383 if (client->exp) {
1384 QTAILQ_REMOVE(&client->exp->clients, client, next);
1385 nbd_export_put(client->exp);
1386 }
1387 g_free(client);
1388 }
1389}
1390
1391static void client_close(NBDClient *client, bool negotiated)
1392{
1393 if (client->closing) {
1394 return;
1395 }
1396
1397 client->closing = true;
1398
1399
1400
1401
1402 qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH,
1403 NULL);
1404
1405
1406 if (client->close_fn) {
1407 client->close_fn(client, negotiated);
1408 }
1409}
1410
1411static NBDRequestData *nbd_request_get(NBDClient *client)
1412{
1413 NBDRequestData *req;
1414
1415 assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
1416 client->nb_requests++;
1417
1418 req = g_new0(NBDRequestData, 1);
1419 nbd_client_get(client);
1420 req->client = client;
1421 return req;
1422}
1423
1424static void nbd_request_put(NBDRequestData *req)
1425{
1426 NBDClient *client = req->client;
1427
1428 if (req->data) {
1429 qemu_vfree(req->data);
1430 }
1431 g_free(req);
1432
1433 client->nb_requests--;
1434 nbd_client_receive_next_request(client);
1435
1436 nbd_client_put(client);
1437}
1438
1439static void blk_aio_attached(AioContext *ctx, void *opaque)
1440{
1441 NBDExport *exp = opaque;
1442 NBDClient *client;
1443
1444 trace_nbd_blk_aio_attached(exp->name, ctx);
1445
1446 exp->ctx = ctx;
1447
1448 QTAILQ_FOREACH(client, &exp->clients, next) {
1449 qio_channel_attach_aio_context(client->ioc, ctx);
1450 if (client->recv_coroutine) {
1451 aio_co_schedule(ctx, client->recv_coroutine);
1452 }
1453 if (client->send_coroutine) {
1454 aio_co_schedule(ctx, client->send_coroutine);
1455 }
1456 }
1457}
1458
1459static void blk_aio_detach(void *opaque)
1460{
1461 NBDExport *exp = opaque;
1462 NBDClient *client;
1463
1464 trace_nbd_blk_aio_detach(exp->name, exp->ctx);
1465
1466 QTAILQ_FOREACH(client, &exp->clients, next) {
1467 qio_channel_detach_aio_context(client->ioc);
1468 }
1469
1470 exp->ctx = NULL;
1471}
1472
1473static void nbd_eject_notifier(Notifier *n, void *data)
1474{
1475 NBDExport *exp = container_of(n, NBDExport, eject_notifier);
1476 AioContext *aio_context;
1477
1478 aio_context = exp->ctx;
1479 aio_context_acquire(aio_context);
1480 nbd_export_close(exp);
1481 aio_context_release(aio_context);
1482}
1483
1484NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset,
1485 uint64_t size, const char *name, const char *desc,
1486 const char *bitmap, bool readonly, bool shared,
1487 void (*close)(NBDExport *), bool writethrough,
1488 BlockBackend *on_eject_blk, Error **errp)
1489{
1490 AioContext *ctx;
1491 BlockBackend *blk;
1492 NBDExport *exp = g_new0(NBDExport, 1);
1493 uint64_t perm;
1494 int ret;
1495
1496
1497
1498
1499
1500
1501
1502 assert(name && strlen(name) <= NBD_MAX_STRING_SIZE);
1503 ctx = bdrv_get_aio_context(bs);
1504 bdrv_invalidate_cache(bs, NULL);
1505
1506
1507
1508 perm = BLK_PERM_CONSISTENT_READ;
1509 if (!readonly) {
1510 perm |= BLK_PERM_WRITE;
1511 }
1512 blk = blk_new(ctx, perm,
1513 BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
1514 BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD);
1515 ret = blk_insert_bs(blk, bs, errp);
1516 if (ret < 0) {
1517 goto fail;
1518 }
1519 blk_set_enable_write_cache(blk, !writethrough);
1520 blk_set_allow_aio_context_change(blk, true);
1521
1522 exp->refcount = 1;
1523 QTAILQ_INIT(&exp->clients);
1524 exp->blk = blk;
1525 assert(dev_offset <= INT64_MAX);
1526 exp->dev_offset = dev_offset;
1527 exp->name = g_strdup(name);
1528 assert(!desc || strlen(desc) <= NBD_MAX_STRING_SIZE);
1529 exp->description = g_strdup(desc);
1530 exp->nbdflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FLUSH |
1531 NBD_FLAG_SEND_FUA | NBD_FLAG_SEND_CACHE);
1532 if (readonly) {
1533 exp->nbdflags |= NBD_FLAG_READ_ONLY;
1534 if (shared) {
1535 exp->nbdflags |= NBD_FLAG_CAN_MULTI_CONN;
1536 }
1537 } else {
1538 exp->nbdflags |= (NBD_FLAG_SEND_TRIM | NBD_FLAG_SEND_WRITE_ZEROES |
1539 NBD_FLAG_SEND_FAST_ZERO);
1540 }
1541 assert(size <= INT64_MAX - dev_offset);
1542 exp->size = QEMU_ALIGN_DOWN(size, BDRV_SECTOR_SIZE);
1543
1544 if (bitmap) {
1545 BdrvDirtyBitmap *bm = NULL;
1546
1547 while (true) {
1548 bm = bdrv_find_dirty_bitmap(bs, bitmap);
1549 if (bm != NULL || bs->backing == NULL) {
1550 break;
1551 }
1552
1553 bs = bs->backing->bs;
1554 }
1555
1556 if (bm == NULL) {
1557 error_setg(errp, "Bitmap '%s' is not found", bitmap);
1558 goto fail;
1559 }
1560
1561 if (bdrv_dirty_bitmap_check(bm, BDRV_BITMAP_ALLOW_RO, errp)) {
1562 goto fail;
1563 }
1564
1565 if (readonly && bdrv_is_writable(bs) &&
1566 bdrv_dirty_bitmap_enabled(bm)) {
1567 error_setg(errp,
1568 "Enabled bitmap '%s' incompatible with readonly export",
1569 bitmap);
1570 goto fail;
1571 }
1572
1573 bdrv_dirty_bitmap_set_busy(bm, true);
1574 exp->export_bitmap = bm;
1575 assert(strlen(bitmap) <= BDRV_BITMAP_MAX_NAME_SIZE);
1576 exp->export_bitmap_context = g_strdup_printf("qemu:dirty-bitmap:%s",
1577 bitmap);
1578 assert(strlen(exp->export_bitmap_context) < NBD_MAX_STRING_SIZE);
1579 }
1580
1581 exp->close = close;
1582 exp->ctx = ctx;
1583 blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
1584
1585 if (on_eject_blk) {
1586 blk_ref(on_eject_blk);
1587 exp->eject_notifier_blk = on_eject_blk;
1588 exp->eject_notifier.notify = nbd_eject_notifier;
1589 blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier);
1590 }
1591 QTAILQ_INSERT_TAIL(&exports, exp, next);
1592 nbd_export_get(exp);
1593 return exp;
1594
1595fail:
1596 blk_unref(blk);
1597 g_free(exp->name);
1598 g_free(exp->description);
1599 g_free(exp);
1600 return NULL;
1601}
1602
1603NBDExport *nbd_export_find(const char *name)
1604{
1605 NBDExport *exp;
1606 QTAILQ_FOREACH(exp, &exports, next) {
1607 if (strcmp(name, exp->name) == 0) {
1608 return exp;
1609 }
1610 }
1611
1612 return NULL;
1613}
1614
1615AioContext *
1616nbd_export_aio_context(NBDExport *exp)
1617{
1618 return exp->ctx;
1619}
1620
1621void nbd_export_close(NBDExport *exp)
1622{
1623 NBDClient *client, *next;
1624
1625 nbd_export_get(exp);
1626
1627
1628
1629
1630
1631
1632
1633 QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
1634 client_close(client, true);
1635 }
1636 if (exp->name) {
1637 nbd_export_put(exp);
1638 g_free(exp->name);
1639 exp->name = NULL;
1640 QTAILQ_REMOVE(&exports, exp, next);
1641 }
1642 g_free(exp->description);
1643 exp->description = NULL;
1644 nbd_export_put(exp);
1645}
1646
1647void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp)
1648{
1649 if (mode == NBD_SERVER_REMOVE_MODE_HARD || QTAILQ_EMPTY(&exp->clients)) {
1650 nbd_export_close(exp);
1651 return;
1652 }
1653
1654 assert(mode == NBD_SERVER_REMOVE_MODE_SAFE);
1655
1656 error_setg(errp, "export '%s' still in use", exp->name);
1657 error_append_hint(errp, "Use mode='hard' to force client disconnect\n");
1658}
1659
1660void nbd_export_get(NBDExport *exp)
1661{
1662 assert(exp->refcount > 0);
1663 exp->refcount++;
1664}
1665
1666void nbd_export_put(NBDExport *exp)
1667{
1668 assert(exp->refcount > 0);
1669 if (exp->refcount == 1) {
1670 nbd_export_close(exp);
1671 }
1672
1673
1674
1675
1676
1677
1678 assert(exp->refcount > 0);
1679 if (--exp->refcount == 0) {
1680 assert(exp->name == NULL);
1681 assert(exp->description == NULL);
1682
1683 if (exp->close) {
1684 exp->close(exp);
1685 }
1686
1687 if (exp->blk) {
1688 if (exp->eject_notifier_blk) {
1689 notifier_remove(&exp->eject_notifier);
1690 blk_unref(exp->eject_notifier_blk);
1691 }
1692 blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
1693 blk_aio_detach, exp);
1694 blk_unref(exp->blk);
1695 exp->blk = NULL;
1696 }
1697
1698 if (exp->export_bitmap) {
1699 bdrv_dirty_bitmap_set_busy(exp->export_bitmap, false);
1700 g_free(exp->export_bitmap_context);
1701 }
1702
1703 g_free(exp);
1704 }
1705}
1706
1707BlockBackend *nbd_export_get_blockdev(NBDExport *exp)
1708{
1709 return exp->blk;
1710}
1711
1712void nbd_export_close_all(void)
1713{
1714 NBDExport *exp, *next;
1715 AioContext *aio_context;
1716
1717 QTAILQ_FOREACH_SAFE(exp, &exports, next, next) {
1718 aio_context = exp->ctx;
1719 aio_context_acquire(aio_context);
1720 nbd_export_close(exp);
1721 aio_context_release(aio_context);
1722 }
1723}
1724
1725static int coroutine_fn nbd_co_send_iov(NBDClient *client, struct iovec *iov,
1726 unsigned niov, Error **errp)
1727{
1728 int ret;
1729
1730 g_assert(qemu_in_coroutine());
1731 qemu_co_mutex_lock(&client->send_lock);
1732 client->send_coroutine = qemu_coroutine_self();
1733
1734 ret = qio_channel_writev_all(client->ioc, iov, niov, errp) < 0 ? -EIO : 0;
1735
1736 client->send_coroutine = NULL;
1737 qemu_co_mutex_unlock(&client->send_lock);
1738
1739 return ret;
1740}
1741
1742static inline void set_be_simple_reply(NBDSimpleReply *reply, uint64_t error,
1743 uint64_t handle)
1744{
1745 stl_be_p(&reply->magic, NBD_SIMPLE_REPLY_MAGIC);
1746 stl_be_p(&reply->error, error);
1747 stq_be_p(&reply->handle, handle);
1748}
1749
1750static int nbd_co_send_simple_reply(NBDClient *client,
1751 uint64_t handle,
1752 uint32_t error,
1753 void *data,
1754 size_t len,
1755 Error **errp)
1756{
1757 NBDSimpleReply reply;
1758 int nbd_err = system_errno_to_nbd_errno(error);
1759 struct iovec iov[] = {
1760 {.iov_base = &reply, .iov_len = sizeof(reply)},
1761 {.iov_base = data, .iov_len = len}
1762 };
1763
1764 trace_nbd_co_send_simple_reply(handle, nbd_err, nbd_err_lookup(nbd_err),
1765 len);
1766 set_be_simple_reply(&reply, nbd_err, handle);
1767
1768 return nbd_co_send_iov(client, iov, len ? 2 : 1, errp);
1769}
1770
1771static inline void set_be_chunk(NBDStructuredReplyChunk *chunk, uint16_t flags,
1772 uint16_t type, uint64_t handle, uint32_t length)
1773{
1774 stl_be_p(&chunk->magic, NBD_STRUCTURED_REPLY_MAGIC);
1775 stw_be_p(&chunk->flags, flags);
1776 stw_be_p(&chunk->type, type);
1777 stq_be_p(&chunk->handle, handle);
1778 stl_be_p(&chunk->length, length);
1779}
1780
1781static int coroutine_fn nbd_co_send_structured_done(NBDClient *client,
1782 uint64_t handle,
1783 Error **errp)
1784{
1785 NBDStructuredReplyChunk chunk;
1786 struct iovec iov[] = {
1787 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
1788 };
1789
1790 trace_nbd_co_send_structured_done(handle);
1791 set_be_chunk(&chunk, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_NONE, handle, 0);
1792
1793 return nbd_co_send_iov(client, iov, 1, errp);
1794}
1795
1796static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,
1797 uint64_t handle,
1798 uint64_t offset,
1799 void *data,
1800 size_t size,
1801 bool final,
1802 Error **errp)
1803{
1804 NBDStructuredReadData chunk;
1805 struct iovec iov[] = {
1806 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
1807 {.iov_base = data, .iov_len = size}
1808 };
1809
1810 assert(size);
1811 trace_nbd_co_send_structured_read(handle, offset, data, size);
1812 set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0,
1813 NBD_REPLY_TYPE_OFFSET_DATA, handle,
1814 sizeof(chunk) - sizeof(chunk.h) + size);
1815 stq_be_p(&chunk.offset, offset);
1816
1817 return nbd_co_send_iov(client, iov, 2, errp);
1818}
1819
1820static int coroutine_fn nbd_co_send_structured_error(NBDClient *client,
1821 uint64_t handle,
1822 uint32_t error,
1823 const char *msg,
1824 Error **errp)
1825{
1826 NBDStructuredError chunk;
1827 int nbd_err = system_errno_to_nbd_errno(error);
1828 struct iovec iov[] = {
1829 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
1830 {.iov_base = (char *)msg, .iov_len = msg ? strlen(msg) : 0},
1831 };
1832
1833 assert(nbd_err);
1834 trace_nbd_co_send_structured_error(handle, nbd_err,
1835 nbd_err_lookup(nbd_err), msg ? msg : "");
1836 set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_ERROR, handle,
1837 sizeof(chunk) - sizeof(chunk.h) + iov[1].iov_len);
1838 stl_be_p(&chunk.error, nbd_err);
1839 stw_be_p(&chunk.message_length, iov[1].iov_len);
1840
1841 return nbd_co_send_iov(client, iov, 1 + !!iov[1].iov_len, errp);
1842}
1843
1844
1845
1846
1847
1848static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
1849 uint64_t handle,
1850 uint64_t offset,
1851 uint8_t *data,
1852 size_t size,
1853 Error **errp)
1854{
1855 int ret = 0;
1856 NBDExport *exp = client->exp;
1857 size_t progress = 0;
1858
1859 while (progress < size) {
1860 int64_t pnum;
1861 int status = bdrv_block_status_above(blk_bs(exp->blk), NULL,
1862 offset + progress,
1863 size - progress, &pnum, NULL,
1864 NULL);
1865 bool final;
1866
1867 if (status < 0) {
1868 char *msg = g_strdup_printf("unable to check for holes: %s",
1869 strerror(-status));
1870
1871 ret = nbd_co_send_structured_error(client, handle, -status, msg,
1872 errp);
1873 g_free(msg);
1874 return ret;
1875 }
1876 assert(pnum && pnum <= size - progress);
1877 final = progress + pnum == size;
1878 if (status & BDRV_BLOCK_ZERO) {
1879 NBDStructuredReadHole chunk;
1880 struct iovec iov[] = {
1881 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
1882 };
1883
1884 trace_nbd_co_send_structured_read_hole(handle, offset + progress,
1885 pnum);
1886 set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0,
1887 NBD_REPLY_TYPE_OFFSET_HOLE,
1888 handle, sizeof(chunk) - sizeof(chunk.h));
1889 stq_be_p(&chunk.offset, offset + progress);
1890 stl_be_p(&chunk.length, pnum);
1891 ret = nbd_co_send_iov(client, iov, 1, errp);
1892 } else {
1893 ret = blk_pread(exp->blk, offset + progress + exp->dev_offset,
1894 data + progress, pnum);
1895 if (ret < 0) {
1896 error_setg_errno(errp, -ret, "reading from file failed");
1897 break;
1898 }
1899 ret = nbd_co_send_structured_read(client, handle, offset + progress,
1900 data + progress, pnum, final,
1901 errp);
1902 }
1903
1904 if (ret < 0) {
1905 break;
1906 }
1907 progress += pnum;
1908 }
1909 return ret;
1910}
1911
1912typedef struct NBDExtentArray {
1913 NBDExtent *extents;
1914 unsigned int nb_alloc;
1915 unsigned int count;
1916 uint64_t total_length;
1917 bool can_add;
1918 bool converted_to_be;
1919} NBDExtentArray;
1920
1921static NBDExtentArray *nbd_extent_array_new(unsigned int nb_alloc)
1922{
1923 NBDExtentArray *ea = g_new0(NBDExtentArray, 1);
1924
1925 ea->nb_alloc = nb_alloc;
1926 ea->extents = g_new(NBDExtent, nb_alloc);
1927 ea->can_add = true;
1928
1929 return ea;
1930}
1931
1932static void nbd_extent_array_free(NBDExtentArray *ea)
1933{
1934 g_free(ea->extents);
1935 g_free(ea);
1936}
1937G_DEFINE_AUTOPTR_CLEANUP_FUNC(NBDExtentArray, nbd_extent_array_free);
1938
1939
1940static void nbd_extent_array_convert_to_be(NBDExtentArray *ea)
1941{
1942 int i;
1943
1944 assert(!ea->converted_to_be);
1945 ea->can_add = false;
1946 ea->converted_to_be = true;
1947
1948 for (i = 0; i < ea->count; i++) {
1949 ea->extents[i].flags = cpu_to_be32(ea->extents[i].flags);
1950 ea->extents[i].length = cpu_to_be32(ea->extents[i].length);
1951 }
1952}
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964static int nbd_extent_array_add(NBDExtentArray *ea,
1965 uint32_t length, uint32_t flags)
1966{
1967 assert(ea->can_add);
1968
1969 if (!length) {
1970 return 0;
1971 }
1972
1973
1974 if (ea->count > 0 && flags == ea->extents[ea->count - 1].flags) {
1975 uint64_t sum = (uint64_t)length + ea->extents[ea->count - 1].length;
1976
1977 if (sum <= UINT32_MAX) {
1978 ea->extents[ea->count - 1].length = sum;
1979 ea->total_length += length;
1980 return 0;
1981 }
1982 }
1983
1984 if (ea->count >= ea->nb_alloc) {
1985 ea->can_add = false;
1986 return -1;
1987 }
1988
1989 ea->total_length += length;
1990 ea->extents[ea->count] = (NBDExtent) {.length = length, .flags = flags};
1991 ea->count++;
1992
1993 return 0;
1994}
1995
1996static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset,
1997 uint64_t bytes, NBDExtentArray *ea)
1998{
1999 while (bytes) {
2000 uint32_t flags;
2001 int64_t num;
2002 int ret = bdrv_block_status_above(bs, NULL, offset, bytes, &num,
2003 NULL, NULL);
2004
2005 if (ret < 0) {
2006 return ret;
2007 }
2008
2009 flags = (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) |
2010 (ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0);
2011
2012 if (nbd_extent_array_add(ea, num, flags) < 0) {
2013 return 0;
2014 }
2015
2016 offset += num;
2017 bytes -= num;
2018 }
2019
2020 return 0;
2021}
2022
2023
2024
2025
2026
2027
2028
2029static int nbd_co_send_extents(NBDClient *client, uint64_t handle,
2030 NBDExtentArray *ea,
2031 bool last, uint32_t context_id, Error **errp)
2032{
2033 NBDStructuredMeta chunk;
2034 struct iovec iov[] = {
2035 {.iov_base = &chunk, .iov_len = sizeof(chunk)},
2036 {.iov_base = ea->extents, .iov_len = ea->count * sizeof(ea->extents[0])}
2037 };
2038
2039 nbd_extent_array_convert_to_be(ea);
2040
2041 trace_nbd_co_send_extents(handle, ea->count, context_id, ea->total_length,
2042 last);
2043 set_be_chunk(&chunk.h, last ? NBD_REPLY_FLAG_DONE : 0,
2044 NBD_REPLY_TYPE_BLOCK_STATUS,
2045 handle, sizeof(chunk) - sizeof(chunk.h) + iov[1].iov_len);
2046 stl_be_p(&chunk.context_id, context_id);
2047
2048 return nbd_co_send_iov(client, iov, 2, errp);
2049}
2050
2051
2052static int nbd_co_send_block_status(NBDClient *client, uint64_t handle,
2053 BlockDriverState *bs, uint64_t offset,
2054 uint32_t length, bool dont_fragment,
2055 bool last, uint32_t context_id,
2056 Error **errp)
2057{
2058 int ret;
2059 unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS;
2060 g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents);
2061
2062 ret = blockstatus_to_extents(bs, offset, length, ea);
2063 if (ret < 0) {
2064 return nbd_co_send_structured_error(
2065 client, handle, -ret, "can't get block status", errp);
2066 }
2067
2068 return nbd_co_send_extents(client, handle, ea, last, context_id, errp);
2069}
2070
2071
2072static void bitmap_to_extents(BdrvDirtyBitmap *bitmap,
2073 uint64_t offset, uint64_t length,
2074 NBDExtentArray *es)
2075{
2076 int64_t start, dirty_start, dirty_count;
2077 int64_t end = offset + length;
2078 bool full = false;
2079
2080 bdrv_dirty_bitmap_lock(bitmap);
2081
2082 for (start = offset;
2083 bdrv_dirty_bitmap_next_dirty_area(bitmap, start, end, INT32_MAX,
2084 &dirty_start, &dirty_count);
2085 start = dirty_start + dirty_count)
2086 {
2087 if ((nbd_extent_array_add(es, dirty_start - start, 0) < 0) ||
2088 (nbd_extent_array_add(es, dirty_count, NBD_STATE_DIRTY) < 0))
2089 {
2090 full = true;
2091 break;
2092 }
2093 }
2094
2095 if (!full) {
2096
2097 nbd_extent_array_add(es, end - start, 0);
2098 }
2099
2100 bdrv_dirty_bitmap_unlock(bitmap);
2101}
2102
2103static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle,
2104 BdrvDirtyBitmap *bitmap, uint64_t offset,
2105 uint32_t length, bool dont_fragment, bool last,
2106 uint32_t context_id, Error **errp)
2107{
2108 unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS;
2109 g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents);
2110
2111 bitmap_to_extents(bitmap, offset, length, ea);
2112
2113 return nbd_co_send_extents(client, handle, ea, last, context_id, errp);
2114}
2115
2116
2117
2118
2119
2120
2121
2122static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
2123 Error **errp)
2124{
2125 NBDClient *client = req->client;
2126 int valid_flags;
2127
2128 g_assert(qemu_in_coroutine());
2129 assert(client->recv_coroutine == qemu_coroutine_self());
2130 if (nbd_receive_request(client->ioc, request, errp) < 0) {
2131 return -EIO;
2132 }
2133
2134 trace_nbd_co_receive_request_decode_type(request->handle, request->type,
2135 nbd_cmd_lookup(request->type));
2136
2137 if (request->type != NBD_CMD_WRITE) {
2138
2139 req->complete = true;
2140 }
2141
2142 if (request->type == NBD_CMD_DISC) {
2143
2144
2145 return -EIO;
2146 }
2147
2148 if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE ||
2149 request->type == NBD_CMD_CACHE)
2150 {
2151 if (request->len > NBD_MAX_BUFFER_SIZE) {
2152 error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
2153 request->len, NBD_MAX_BUFFER_SIZE);
2154 return -EINVAL;
2155 }
2156
2157 if (request->type != NBD_CMD_CACHE) {
2158 req->data = blk_try_blockalign(client->exp->blk, request->len);
2159 if (req->data == NULL) {
2160 error_setg(errp, "No memory");
2161 return -ENOMEM;
2162 }
2163 }
2164 }
2165
2166 if (request->type == NBD_CMD_WRITE) {
2167 if (nbd_read(client->ioc, req->data, request->len, "CMD_WRITE data",
2168 errp) < 0)
2169 {
2170 return -EIO;
2171 }
2172 req->complete = true;
2173
2174 trace_nbd_co_receive_request_payload_received(request->handle,
2175 request->len);
2176 }
2177
2178
2179 if (client->exp->nbdflags & NBD_FLAG_READ_ONLY &&
2180 (request->type == NBD_CMD_WRITE ||
2181 request->type == NBD_CMD_WRITE_ZEROES ||
2182 request->type == NBD_CMD_TRIM)) {
2183 error_setg(errp, "Export is read-only");
2184 return -EROFS;
2185 }
2186 if (request->from > client->exp->size ||
2187 request->len > client->exp->size - request->from) {
2188 error_setg(errp, "operation past EOF; From: %" PRIu64 ", Len: %" PRIu32
2189 ", Size: %" PRIu64, request->from, request->len,
2190 client->exp->size);
2191 return (request->type == NBD_CMD_WRITE ||
2192 request->type == NBD_CMD_WRITE_ZEROES) ? -ENOSPC : -EINVAL;
2193 }
2194 if (client->check_align && !QEMU_IS_ALIGNED(request->from | request->len,
2195 client->check_align)) {
2196
2197
2198
2199
2200 trace_nbd_co_receive_align_compliance(nbd_cmd_lookup(request->type),
2201 request->from,
2202 request->len,
2203 client->check_align);
2204 }
2205 valid_flags = NBD_CMD_FLAG_FUA;
2206 if (request->type == NBD_CMD_READ && client->structured_reply) {
2207 valid_flags |= NBD_CMD_FLAG_DF;
2208 } else if (request->type == NBD_CMD_WRITE_ZEROES) {
2209 valid_flags |= NBD_CMD_FLAG_NO_HOLE | NBD_CMD_FLAG_FAST_ZERO;
2210 } else if (request->type == NBD_CMD_BLOCK_STATUS) {
2211 valid_flags |= NBD_CMD_FLAG_REQ_ONE;
2212 }
2213 if (request->flags & ~valid_flags) {
2214 error_setg(errp, "unsupported flags for command %s (got 0x%x)",
2215 nbd_cmd_lookup(request->type), request->flags);
2216 return -EINVAL;
2217 }
2218
2219 return 0;
2220}
2221
2222
2223
2224
2225
2226static coroutine_fn int nbd_send_generic_reply(NBDClient *client,
2227 uint64_t handle,
2228 int ret,
2229 const char *error_msg,
2230 Error **errp)
2231{
2232 if (client->structured_reply && ret < 0) {
2233 return nbd_co_send_structured_error(client, handle, -ret, error_msg,
2234 errp);
2235 } else {
2236 return nbd_co_send_simple_reply(client, handle, ret < 0 ? -ret : 0,
2237 NULL, 0, errp);
2238 }
2239}
2240
2241
2242
2243
2244static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
2245 uint8_t *data, Error **errp)
2246{
2247 int ret;
2248 NBDExport *exp = client->exp;
2249
2250 assert(request->type == NBD_CMD_READ);
2251
2252
2253 if (request->flags & NBD_CMD_FLAG_FUA) {
2254 ret = blk_co_flush(exp->blk);
2255 if (ret < 0) {
2256 return nbd_send_generic_reply(client, request->handle, ret,
2257 "flush failed", errp);
2258 }
2259 }
2260
2261 if (client->structured_reply && !(request->flags & NBD_CMD_FLAG_DF) &&
2262 request->len)
2263 {
2264 return nbd_co_send_sparse_read(client, request->handle, request->from,
2265 data, request->len, errp);
2266 }
2267
2268 ret = blk_pread(exp->blk, request->from + exp->dev_offset, data,
2269 request->len);
2270 if (ret < 0) {
2271 return nbd_send_generic_reply(client, request->handle, ret,
2272 "reading from file failed", errp);
2273 }
2274
2275 if (client->structured_reply) {
2276 if (request->len) {
2277 return nbd_co_send_structured_read(client, request->handle,
2278 request->from, data,
2279 request->len, true, errp);
2280 } else {
2281 return nbd_co_send_structured_done(client, request->handle, errp);
2282 }
2283 } else {
2284 return nbd_co_send_simple_reply(client, request->handle, 0,
2285 data, request->len, errp);
2286 }
2287}
2288
2289
2290
2291
2292
2293
2294
2295
2296static coroutine_fn int nbd_do_cmd_cache(NBDClient *client, NBDRequest *request,
2297 Error **errp)
2298{
2299 int ret;
2300 NBDExport *exp = client->exp;
2301
2302 assert(request->type == NBD_CMD_CACHE);
2303
2304 ret = blk_co_preadv(exp->blk, request->from + exp->dev_offset, request->len,
2305 NULL, BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH);
2306
2307 return nbd_send_generic_reply(client, request->handle, ret,
2308 "caching data failed", errp);
2309}
2310
2311
2312
2313
2314static coroutine_fn int nbd_handle_request(NBDClient *client,
2315 NBDRequest *request,
2316 uint8_t *data, Error **errp)
2317{
2318 int ret;
2319 int flags;
2320 NBDExport *exp = client->exp;
2321 char *msg;
2322
2323 switch (request->type) {
2324 case NBD_CMD_CACHE:
2325 return nbd_do_cmd_cache(client, request, errp);
2326
2327 case NBD_CMD_READ:
2328 return nbd_do_cmd_read(client, request, data, errp);
2329
2330 case NBD_CMD_WRITE:
2331 flags = 0;
2332 if (request->flags & NBD_CMD_FLAG_FUA) {
2333 flags |= BDRV_REQ_FUA;
2334 }
2335 ret = blk_pwrite(exp->blk, request->from + exp->dev_offset,
2336 data, request->len, flags);
2337 return nbd_send_generic_reply(client, request->handle, ret,
2338 "writing to file failed", errp);
2339
2340 case NBD_CMD_WRITE_ZEROES:
2341 flags = 0;
2342 if (request->flags & NBD_CMD_FLAG_FUA) {
2343 flags |= BDRV_REQ_FUA;
2344 }
2345 if (!(request->flags & NBD_CMD_FLAG_NO_HOLE)) {
2346 flags |= BDRV_REQ_MAY_UNMAP;
2347 }
2348 if (request->flags & NBD_CMD_FLAG_FAST_ZERO) {
2349 flags |= BDRV_REQ_NO_FALLBACK;
2350 }
2351 ret = blk_pwrite_zeroes(exp->blk, request->from + exp->dev_offset,
2352 request->len, flags);
2353 return nbd_send_generic_reply(client, request->handle, ret,
2354 "writing to file failed", errp);
2355
2356 case NBD_CMD_DISC:
2357
2358 abort();
2359
2360 case NBD_CMD_FLUSH:
2361 ret = blk_co_flush(exp->blk);
2362 return nbd_send_generic_reply(client, request->handle, ret,
2363 "flush failed", errp);
2364
2365 case NBD_CMD_TRIM:
2366 ret = blk_co_pdiscard(exp->blk, request->from + exp->dev_offset,
2367 request->len);
2368 if (ret == 0 && request->flags & NBD_CMD_FLAG_FUA) {
2369 ret = blk_co_flush(exp->blk);
2370 }
2371 return nbd_send_generic_reply(client, request->handle, ret,
2372 "discard failed", errp);
2373
2374 case NBD_CMD_BLOCK_STATUS:
2375 if (!request->len) {
2376 return nbd_send_generic_reply(client, request->handle, -EINVAL,
2377 "need non-zero length", errp);
2378 }
2379 if (client->export_meta.valid &&
2380 (client->export_meta.base_allocation ||
2381 client->export_meta.bitmap))
2382 {
2383 bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE;
2384
2385 if (client->export_meta.base_allocation) {
2386 ret = nbd_co_send_block_status(client, request->handle,
2387 blk_bs(exp->blk), request->from,
2388 request->len, dont_fragment,
2389 !client->export_meta.bitmap,
2390 NBD_META_ID_BASE_ALLOCATION,
2391 errp);
2392 if (ret < 0) {
2393 return ret;
2394 }
2395 }
2396
2397 if (client->export_meta.bitmap) {
2398 ret = nbd_co_send_bitmap(client, request->handle,
2399 client->exp->export_bitmap,
2400 request->from, request->len,
2401 dont_fragment,
2402 true, NBD_META_ID_DIRTY_BITMAP, errp);
2403 if (ret < 0) {
2404 return ret;
2405 }
2406 }
2407
2408 return 0;
2409 } else {
2410 return nbd_send_generic_reply(client, request->handle, -EINVAL,
2411 "CMD_BLOCK_STATUS not negotiated",
2412 errp);
2413 }
2414
2415 default:
2416 msg = g_strdup_printf("invalid request type (%" PRIu32 ") received",
2417 request->type);
2418 ret = nbd_send_generic_reply(client, request->handle, -EINVAL, msg,
2419 errp);
2420 g_free(msg);
2421 return ret;
2422 }
2423}
2424
2425
2426static coroutine_fn void nbd_trip(void *opaque)
2427{
2428 NBDClient *client = opaque;
2429 NBDRequestData *req;
2430 NBDRequest request = { 0 };
2431 int ret;
2432 Error *local_err = NULL;
2433
2434 trace_nbd_trip();
2435 if (client->closing) {
2436 nbd_client_put(client);
2437 return;
2438 }
2439
2440 req = nbd_request_get(client);
2441 ret = nbd_co_receive_request(req, &request, &local_err);
2442 client->recv_coroutine = NULL;
2443
2444 if (client->closing) {
2445
2446
2447
2448
2449 goto done;
2450 }
2451
2452 nbd_client_receive_next_request(client);
2453 if (ret == -EIO) {
2454 goto disconnect;
2455 }
2456
2457 if (ret < 0) {
2458
2459
2460 Error *export_err = local_err;
2461
2462 local_err = NULL;
2463 ret = nbd_send_generic_reply(client, request.handle, -EINVAL,
2464 error_get_pretty(export_err), &local_err);
2465 error_free(export_err);
2466 } else {
2467 ret = nbd_handle_request(client, &request, req->data, &local_err);
2468 }
2469 if (ret < 0) {
2470 error_prepend(&local_err, "Failed to send reply: ");
2471 goto disconnect;
2472 }
2473
2474
2475
2476
2477 if (!req->complete) {
2478 error_setg(&local_err, "Request handling failed in intermediate state");
2479 goto disconnect;
2480 }
2481
2482done:
2483 nbd_request_put(req);
2484 nbd_client_put(client);
2485 return;
2486
2487disconnect:
2488 if (local_err) {
2489 error_reportf_err(local_err, "Disconnect client, due to: ");
2490 }
2491 nbd_request_put(req);
2492 client_close(client, true);
2493 nbd_client_put(client);
2494}
2495
2496static void nbd_client_receive_next_request(NBDClient *client)
2497{
2498 if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS) {
2499 nbd_client_get(client);
2500 client->recv_coroutine = qemu_coroutine_create(nbd_trip, client);
2501 aio_co_schedule(client->exp->ctx, client->recv_coroutine);
2502 }
2503}
2504
2505static coroutine_fn void nbd_co_client_start(void *opaque)
2506{
2507 NBDClient *client = opaque;
2508 Error *local_err = NULL;
2509
2510 qemu_co_mutex_init(&client->send_lock);
2511
2512 if (nbd_negotiate(client, &local_err)) {
2513 if (local_err) {
2514 error_report_err(local_err);
2515 }
2516 client_close(client, false);
2517 return;
2518 }
2519
2520 nbd_client_receive_next_request(client);
2521}
2522
2523
2524
2525
2526
2527
2528void nbd_client_new(QIOChannelSocket *sioc,
2529 QCryptoTLSCreds *tlscreds,
2530 const char *tlsauthz,
2531 void (*close_fn)(NBDClient *, bool))
2532{
2533 NBDClient *client;
2534 Coroutine *co;
2535
2536 client = g_new0(NBDClient, 1);
2537 client->refcount = 1;
2538 client->tlscreds = tlscreds;
2539 if (tlscreds) {
2540 object_ref(OBJECT(client->tlscreds));
2541 }
2542 client->tlsauthz = g_strdup(tlsauthz);
2543 client->sioc = sioc;
2544 object_ref(OBJECT(client->sioc));
2545 client->ioc = QIO_CHANNEL(sioc);
2546 object_ref(OBJECT(client->ioc));
2547 client->close_fn = close_fn;
2548
2549 co = qemu_coroutine_create(nbd_co_client_start, client);
2550 qemu_coroutine_enter(co);
2551}
2552