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