31
#include "qemu/osdep.h"
34
#include "qemu/option.h"
35
#include "qemu/cutils.h"
36
#include "qemu/main-loop.h"
38
#include "qapi/qapi-visit-sockets.h"
39
#include "qapi/qmp/qstring.h"
40
#include "qapi/clone-visitor.h"
42
#include "block/qdict.h"
44
#include "block/block_int.h"
45
#include "block/coroutines.h"
49
#define EN_OPTSTR ":exportname="
50
#define MAX_NBD_REQUESTS 16
52
#define COOKIE_TO_INDEX(cookie) ((cookie) - 1)
53
#define INDEX_TO_COOKIE(index) ((index) + 1)
61
typedef enum NBDClientState {
62
NBD_CLIENT_CONNECTING_WAIT,
63
NBD_CLIENT_CONNECTING_NOWAIT,
68
typedef struct BDRVNBDState {
76
QemuMutex requests_lock;
80
NBDClientRequest requests[MAX_NBD_REQUESTS];
81
QEMUTimer *reconnect_delay_timer;
90
CoMutex receive_mutex;
93
QEMUTimer *open_timer;
98
uint32_t reconnect_delay;
99
uint32_t open_timeout;
100
SocketAddress *saddr;
103
QCryptoTLSCreds *tlscreds;
105
char *x_dirty_bitmap;
108
NBDClientConnection *conn;
111
static void nbd_yank(void *opaque);
113
static void nbd_clear_bdrvstate(BlockDriverState *bs)
115
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
117
nbd_client_connection_release(s->conn);
120
yank_unregister_instance(BLOCKDEV_YANK_INSTANCE(bs->node_name));
123
assert(!s->reconnect_delay_timer);
124
assert(!s->open_timer);
126
object_unref(OBJECT(s->tlscreds));
127
qapi_free_SocketAddress(s->saddr);
131
g_free(s->tlscredsid);
132
s->tlscredsid = NULL;
133
g_free(s->tlshostname);
134
s->tlshostname = NULL;
135
g_free(s->x_dirty_bitmap);
136
s->x_dirty_bitmap = NULL;
140
static bool coroutine_fn nbd_recv_coroutine_wake_one(NBDClientRequest *req)
142
if (req->receiving) {
143
req->receiving = false;
144
aio_co_wake(req->coroutine);
151
static void coroutine_fn nbd_recv_coroutines_wake(BDRVNBDState *s)
155
QEMU_LOCK_GUARD(&s->receive_mutex);
156
for (i = 0; i < MAX_NBD_REQUESTS; i++) {
157
if (nbd_recv_coroutine_wake_one(&s->requests[i])) {
164
static void coroutine_fn nbd_channel_error_locked(BDRVNBDState *s, int ret)
166
if (s->state == NBD_CLIENT_CONNECTED) {
167
qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
171
if (s->state == NBD_CLIENT_CONNECTED) {
172
s->state = s->reconnect_delay ? NBD_CLIENT_CONNECTING_WAIT :
173
NBD_CLIENT_CONNECTING_NOWAIT;
176
s->state = NBD_CLIENT_QUIT;
180
static void coroutine_fn nbd_channel_error(BDRVNBDState *s, int ret)
182
QEMU_LOCK_GUARD(&s->requests_lock);
183
nbd_channel_error_locked(s, ret);
186
static void reconnect_delay_timer_del(BDRVNBDState *s)
188
if (s->reconnect_delay_timer) {
189
timer_free(s->reconnect_delay_timer);
190
s->reconnect_delay_timer = NULL;
194
static void reconnect_delay_timer_cb(void *opaque)
196
BDRVNBDState *s = opaque;
198
reconnect_delay_timer_del(s);
199
WITH_QEMU_LOCK_GUARD(&s->requests_lock) {
200
if (s->state != NBD_CLIENT_CONNECTING_WAIT) {
203
s->state = NBD_CLIENT_CONNECTING_NOWAIT;
205
nbd_co_establish_connection_cancel(s->conn);
208
static void reconnect_delay_timer_init(BDRVNBDState *s, uint64_t expire_time_ns)
210
assert(!s->reconnect_delay_timer);
211
s->reconnect_delay_timer = aio_timer_new(bdrv_get_aio_context(s->bs),
214
reconnect_delay_timer_cb, s);
215
timer_mod(s->reconnect_delay_timer, expire_time_ns);
218
static void nbd_teardown_connection(BlockDriverState *bs)
220
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
222
assert(!s->in_flight);
225
qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
226
yank_unregister_function(BLOCKDEV_YANK_INSTANCE(s->bs->node_name),
228
object_unref(OBJECT(s->ioc));
232
WITH_QEMU_LOCK_GUARD(&s->requests_lock) {
233
s->state = NBD_CLIENT_QUIT;
237
static void open_timer_del(BDRVNBDState *s)
240
timer_free(s->open_timer);
241
s->open_timer = NULL;
245
static void open_timer_cb(void *opaque)
247
BDRVNBDState *s = opaque;
249
nbd_co_establish_connection_cancel(s->conn);
253
static void open_timer_init(BDRVNBDState *s, uint64_t expire_time_ns)
255
assert(!s->open_timer);
256
s->open_timer = aio_timer_new(bdrv_get_aio_context(s->bs),
260
timer_mod(s->open_timer, expire_time_ns);
263
static bool nbd_client_will_reconnect(BDRVNBDState *s)
268
QEMU_LOCK_GUARD(&s->requests_lock);
269
return s->state == NBD_CLIENT_CONNECTING_WAIT;
277
static int coroutine_fn GRAPH_RDLOCK
278
nbd_handle_updated_info(BlockDriverState *bs, Error **errp)
280
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
283
if (s->x_dirty_bitmap) {
284
if (!s->info.base_allocation) {
285
error_setg(errp, "requested x-dirty-bitmap %s not found",
289
if (strcmp(s->x_dirty_bitmap, "qemu:allocation-depth") == 0) {
290
s->alloc_depth = true;
294
if (s->info.flags & NBD_FLAG_READ_ONLY) {
295
ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
301
if (s->info.flags & NBD_FLAG_SEND_FUA) {
302
bs->supported_write_flags = BDRV_REQ_FUA;
303
bs->supported_zero_flags |= BDRV_REQ_FUA;
306
if (s->info.flags & NBD_FLAG_SEND_WRITE_ZEROES) {
307
bs->supported_zero_flags |= BDRV_REQ_MAY_UNMAP;
308
if (s->info.flags & NBD_FLAG_SEND_FAST_ZERO) {
309
bs->supported_zero_flags |= BDRV_REQ_NO_FALLBACK;
313
trace_nbd_client_handshake_success(s->export);
318
int coroutine_fn nbd_co_do_establish_connection(BlockDriverState *bs,
319
bool blocking, Error **errp)
321
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
325
assert_bdrv_graph_readable();
328
s->ioc = nbd_co_establish_connection(s->conn, &s->info, blocking, errp);
330
return -ECONNREFUSED;
333
yank_register_function(BLOCKDEV_YANK_INSTANCE(s->bs->node_name), nbd_yank,
336
ret = nbd_handle_updated_info(s->bs, NULL);
342
NBDRequest request = { .type = NBD_CMD_DISC, .mode = s->info.mode };
344
nbd_send_request(s->ioc, &request);
346
yank_unregister_function(BLOCKDEV_YANK_INSTANCE(s->bs->node_name),
348
object_unref(OBJECT(s->ioc));
354
qio_channel_set_blocking(s->ioc, false, NULL);
355
qio_channel_set_follow_coroutine_ctx(s->ioc, true);
358
WITH_QEMU_LOCK_GUARD(&s->requests_lock) {
359
s->state = NBD_CLIENT_CONNECTED;
366
static bool nbd_client_connecting(BDRVNBDState *s)
368
return s->state == NBD_CLIENT_CONNECTING_WAIT ||
369
s->state == NBD_CLIENT_CONNECTING_NOWAIT;
373
static void coroutine_fn GRAPH_RDLOCK nbd_reconnect_attempt(BDRVNBDState *s)
376
bool blocking = s->state == NBD_CLIENT_CONNECTING_WAIT;
382
assert(nbd_client_connecting(s));
383
assert(s->in_flight == 1);
385
trace_nbd_reconnect_attempt(s->bs->in_flight);
387
if (blocking && !s->reconnect_delay_timer) {
392
g_assert(s->reconnect_delay);
393
reconnect_delay_timer_init(s,
394
qemu_clock_get_ns(QEMU_CLOCK_REALTIME) +
395
s->reconnect_delay * NANOSECONDS_PER_SECOND);
400
yank_unregister_function(BLOCKDEV_YANK_INSTANCE(s->bs->node_name),
402
object_unref(OBJECT(s->ioc));
406
qemu_mutex_unlock(&s->requests_lock);
407
ret = nbd_co_do_establish_connection(s->bs, blocking, NULL);
408
trace_nbd_reconnect_attempt_result(ret, s->bs->in_flight);
409
qemu_mutex_lock(&s->requests_lock);
416
reconnect_delay_timer_del(s);
419
static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie,
423
uint64_t ind = COOKIE_TO_INDEX(cookie), ind2;
424
QEMU_LOCK_GUARD(&s->receive_mutex);
427
if (s->reply.cookie == cookie) {
432
if (s->reply.cookie != 0) {
438
ind2 = COOKIE_TO_INDEX(s->reply.cookie);
439
assert(!s->requests[ind2].receiving);
441
s->requests[ind].receiving = true;
442
qemu_co_mutex_unlock(&s->receive_mutex);
444
qemu_coroutine_yield();
454
qemu_co_mutex_lock(&s->receive_mutex);
455
assert(!s->requests[ind].receiving);
460
assert(s->reply.cookie == 0);
461
ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, s->info.mode, errp);
464
error_setg(errp, "server dropped connection");
467
nbd_channel_error(s, ret);
470
if (nbd_reply_is_structured(&s->reply) &&
471
s->info.mode < NBD_MODE_STRUCTURED) {
472
nbd_channel_error(s, -EINVAL);
473
error_setg(errp, "unexpected structured reply");
476
ind2 = COOKIE_TO_INDEX(s->reply.cookie);
477
if (ind2 >= MAX_NBD_REQUESTS || !s->requests[ind2].coroutine) {
478
nbd_channel_error(s, -EINVAL);
479
error_setg(errp, "unexpected cookie value");
482
if (s->reply.cookie == cookie) {
486
nbd_recv_coroutine_wake_one(&s->requests[ind2]);
490
static int coroutine_fn GRAPH_RDLOCK
491
nbd_co_send_request(BlockDriverState *bs, NBDRequest *request,
494
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
497
qemu_mutex_lock(&s->requests_lock);
498
while (s->in_flight == MAX_NBD_REQUESTS ||
499
(s->state != NBD_CLIENT_CONNECTED && s->in_flight > 0)) {
500
qemu_co_queue_wait(&s->free_sema, &s->requests_lock);
504
if (s->state != NBD_CLIENT_CONNECTED) {
505
if (nbd_client_connecting(s)) {
506
nbd_reconnect_attempt(s);
507
qemu_co_queue_restart_all(&s->free_sema);
509
if (s->state != NBD_CLIENT_CONNECTED) {
515
for (i = 0; i < MAX_NBD_REQUESTS; i++) {
516
if (s->requests[i].coroutine == NULL) {
521
assert(i < MAX_NBD_REQUESTS);
522
s->requests[i].coroutine = qemu_coroutine_self();
523
s->requests[i].offset = request->from;
524
s->requests[i].receiving = false;
525
qemu_mutex_unlock(&s->requests_lock);
527
qemu_co_mutex_lock(&s->send_mutex);
528
request->cookie = INDEX_TO_COOKIE(i);
529
request->mode = s->info.mode;
534
qio_channel_set_cork(s->ioc, true);
535
rc = nbd_send_request(s->ioc, request);
536
if (rc >= 0 && qio_channel_writev_all(s->ioc, qiov->iov, qiov->niov,
540
qio_channel_set_cork(s->ioc, false);
542
rc = nbd_send_request(s->ioc, request);
544
qemu_co_mutex_unlock(&s->send_mutex);
547
qemu_mutex_lock(&s->requests_lock);
549
nbd_channel_error_locked(s, rc);
551
s->requests[i].coroutine = NULL;
554
qemu_co_queue_next(&s->free_sema);
555
qemu_mutex_unlock(&s->requests_lock);
560
static inline uint16_t payload_advance16(uint8_t **payload)
563
return lduw_be_p(*payload - 2);
566
static inline uint32_t payload_advance32(uint8_t **payload)
569
return ldl_be_p(*payload - 4);
572
static inline uint64_t payload_advance64(uint8_t **payload)
575
return ldq_be_p(*payload - 8);
578
static int nbd_parse_offset_hole_payload(BDRVNBDState *s,
579
NBDStructuredReplyChunk *chunk,
580
uint8_t *payload, uint64_t orig_offset,
581
QEMUIOVector *qiov, Error **errp)
586
if (chunk->length != sizeof(offset) + sizeof(hole_size)) {
587
error_setg(errp, "Protocol error: invalid payload for "
588
"NBD_REPLY_TYPE_OFFSET_HOLE");
592
offset = payload_advance64(&payload);
593
hole_size = payload_advance32(&payload);
595
if (!hole_size || offset < orig_offset || hole_size > qiov->size ||
596
offset > orig_offset + qiov->size - hole_size) {
597
error_setg(errp, "Protocol error: server sent chunk exceeding requested"
601
if (s->info.min_block &&
602
!QEMU_IS_ALIGNED(hole_size, s->info.min_block)) {
603
trace_nbd_structured_read_compliance("hole");
606
qemu_iovec_memset(qiov, offset - orig_offset, 0, hole_size);
616
static int nbd_parse_blockstatus_payload(BDRVNBDState *s,
617
NBDStructuredReplyChunk *chunk,
618
uint8_t *payload, bool wide,
619
uint64_t orig_length,
620
NBDExtent64 *extent, Error **errp)
624
size_t ext_len = wide ? sizeof(*extent) : sizeof(NBDExtent32);
625
size_t pay_len = sizeof(context_id) + wide * sizeof(count) + ext_len;
628
if (chunk->length < pay_len) {
629
error_setg(errp, "Protocol error: invalid payload for "
630
"NBD_REPLY_TYPE_BLOCK_STATUS");
634
context_id = payload_advance32(&payload);
635
if (s->info.context_id != context_id) {
636
error_setg(errp, "Protocol error: unexpected context id %d for "
637
"NBD_REPLY_TYPE_BLOCK_STATUS, when negotiated context "
638
"id is %d", context_id,
644
count = payload_advance32(&payload);
645
extent->length = payload_advance64(&payload);
646
extent->flags = payload_advance64(&payload);
649
extent->length = payload_advance32(&payload);
650
extent->flags = payload_advance32(&payload);
653
if (extent->length == 0) {
654
error_setg(errp, "Protocol error: server sent status chunk with "
671
if (s->info.min_block && !QEMU_IS_ALIGNED(extent->length,
672
s->info.min_block)) {
673
trace_nbd_parse_blockstatus_compliance("extent length is unaligned");
674
if (extent->length > s->info.min_block) {
675
extent->length = QEMU_ALIGN_DOWN(extent->length,
678
extent->length = s->info.min_block;
693
if (count != wide || chunk->length > pay_len) {
694
trace_nbd_parse_blockstatus_compliance("unexpected extent count");
696
if (extent->length > orig_length) {
697
extent->length = orig_length;
698
trace_nbd_parse_blockstatus_compliance("extent length too large");
707
if (s->alloc_depth && extent->flags > 2) {
718
static int nbd_parse_error_payload(NBDStructuredReplyChunk *chunk,
719
uint8_t *payload, int *request_ret,
723
uint16_t message_size;
725
assert(chunk->type & (1 << 15));
727
if (chunk->length < sizeof(error) + sizeof(message_size)) {
729
"Protocol error: invalid payload for structured error");
733
error = nbd_errno_to_system_errno(payload_advance32(&payload));
735
error_setg(errp, "Protocol error: server sent structured error chunk "
740
*request_ret = -error;
741
message_size = payload_advance16(&payload);
743
if (message_size > chunk->length - sizeof(error) - sizeof(message_size)) {
744
error_setg(errp, "Protocol error: server sent structured error chunk "
745
"with incorrect message size");
756
static int coroutine_fn
757
nbd_co_receive_offset_data_payload(BDRVNBDState *s, uint64_t orig_offset,
758
QEMUIOVector *qiov, Error **errp)
760
QEMUIOVector sub_qiov;
764
NBDStructuredReplyChunk *chunk = &s->reply.structured;
766
assert(nbd_reply_is_structured(&s->reply));
769
if (chunk->length <= sizeof(offset)) {
770
error_setg(errp, "Protocol error: invalid payload for "
771
"NBD_REPLY_TYPE_OFFSET_DATA");
775
if (nbd_read64(s->ioc, &offset, "OFFSET_DATA offset", errp) < 0) {
779
data_size = chunk->length - sizeof(offset);
781
if (offset < orig_offset || data_size > qiov->size ||
782
offset > orig_offset + qiov->size - data_size) {
783
error_setg(errp, "Protocol error: server sent chunk exceeding requested"
787
if (s->info.min_block && !QEMU_IS_ALIGNED(data_size, s->info.min_block)) {
788
trace_nbd_structured_read_compliance("data");
791
qemu_iovec_init(&sub_qiov, qiov->niov);
792
qemu_iovec_concat(&sub_qiov, qiov, offset - orig_offset, data_size);
793
ret = qio_channel_readv_all(s->ioc, sub_qiov.iov, sub_qiov.niov, errp);
794
qemu_iovec_destroy(&sub_qiov);
796
return ret < 0 ? -EIO : 0;
799
#define NBD_MAX_MALLOC_PAYLOAD 1000
800
static coroutine_fn int nbd_co_receive_structured_payload(
801
BDRVNBDState *s, void **payload, Error **errp)
806
assert(nbd_reply_is_structured(&s->reply));
808
len = s->reply.structured.length;
814
if (payload == NULL) {
815
error_setg(errp, "Unexpected structured payload");
819
if (len > NBD_MAX_MALLOC_PAYLOAD) {
820
error_setg(errp, "Payload too large");
824
*payload = g_new(char, len);
825
ret = nbd_read(s->ioc, *payload, len, "structured payload", errp);
850
static coroutine_fn int nbd_co_do_receive_one_chunk(
851
BDRVNBDState *s, uint64_t cookie, bool only_structured,
852
int *request_ret, QEMUIOVector *qiov, void **payload, Error **errp)
856
int i = COOKIE_TO_INDEX(cookie);
857
void *local_payload = NULL;
858
NBDStructuredReplyChunk *chunk;
865
ret = nbd_receive_replies(s, cookie, errp);
867
error_prepend(errp, "Connection closed: ");
872
assert(s->reply.cookie == cookie);
874
if (nbd_reply_is_simple(&s->reply)) {
875
if (only_structured) {
876
error_setg(errp, "Protocol error: simple reply when structured "
877
"reply chunk was expected");
881
*request_ret = -nbd_errno_to_system_errno(s->reply.simple.error);
882
if (*request_ret < 0 || !qiov) {
886
return qio_channel_readv_all(s->ioc, qiov->iov, qiov->niov,
887
errp) < 0 ? -EIO : 0;
891
assert(s->info.mode >= NBD_MODE_STRUCTURED);
892
chunk = &s->reply.structured;
894
if (chunk->type == NBD_REPLY_TYPE_NONE) {
895
if (!(chunk->flags & NBD_REPLY_FLAG_DONE)) {
896
error_setg(errp, "Protocol error: NBD_REPLY_TYPE_NONE chunk without"
897
" NBD_REPLY_FLAG_DONE flag set");
901
error_setg(errp, "Protocol error: NBD_REPLY_TYPE_NONE chunk with"
908
if (chunk->type == NBD_REPLY_TYPE_OFFSET_DATA) {
910
error_setg(errp, "Unexpected NBD_REPLY_TYPE_OFFSET_DATA chunk");
914
return nbd_co_receive_offset_data_payload(s, s->requests[i].offset,
918
if (nbd_reply_type_is_error(chunk->type)) {
919
payload = &local_payload;
922
ret = nbd_co_receive_structured_payload(s, payload, errp);
927
if (nbd_reply_type_is_error(chunk->type)) {
928
ret = nbd_parse_error_payload(chunk, local_payload, request_ret, errp);
929
g_free(local_payload);
941
static coroutine_fn int nbd_co_receive_one_chunk(
942
BDRVNBDState *s, uint64_t cookie, bool only_structured,
943
int *request_ret, QEMUIOVector *qiov, NBDReply *reply, void **payload,
946
int ret = nbd_co_do_receive_one_chunk(s, cookie, only_structured,
947
request_ret, qiov, payload, errp);
950
memset(reply, 0, sizeof(*reply));
951
nbd_channel_error(s, ret);
958
nbd_recv_coroutines_wake(s);
963
typedef struct NBDReplyChunkIter {
967
bool done, only_structured;
970
static void nbd_iter_channel_error(NBDReplyChunkIter *iter,
971
int ret, Error **local_err)
973
assert(local_err && *local_err);
978
error_propagate(&iter->err, *local_err);
980
error_free(*local_err);
986
static void nbd_iter_request_error(NBDReplyChunkIter *iter, int ret)
990
if (!iter->request_ret) {
991
iter->request_ret = ret;
999
#define NBD_FOREACH_REPLY_CHUNK(s, iter, cookie, structured, \
1000
qiov, reply, payload) \
1001
for (iter = (NBDReplyChunkIter) { .only_structured = structured }; \
1002
nbd_reply_chunk_iter_receive(s, &iter, cookie, qiov, reply, payload);)
1008
static bool coroutine_fn nbd_reply_chunk_iter_receive(BDRVNBDState *s,
1009
NBDReplyChunkIter *iter,
1015
int ret, request_ret;
1016
NBDReply local_reply;
1017
NBDStructuredReplyChunk *chunk;
1018
Error *local_err = NULL;
1025
if (reply == NULL) {
1026
reply = &local_reply;
1029
ret = nbd_co_receive_one_chunk(s, cookie, iter->only_structured,
1030
&request_ret, qiov, reply, payload,
1033
nbd_iter_channel_error(iter, ret, &local_err);
1034
} else if (request_ret < 0) {
1035
nbd_iter_request_error(iter, request_ret);
1039
if (nbd_reply_is_simple(reply) || iter->ret < 0) {
1043
chunk = &reply->structured;
1044
iter->only_structured = true;
1046
if (chunk->type == NBD_REPLY_TYPE_NONE) {
1048
assert(chunk->flags & NBD_REPLY_FLAG_DONE);
1052
if (chunk->flags & NBD_REPLY_FLAG_DONE) {
1061
qemu_mutex_lock(&s->requests_lock);
1062
s->requests[COOKIE_TO_INDEX(cookie)].coroutine = NULL;
1064
qemu_co_queue_next(&s->free_sema);
1065
qemu_mutex_unlock(&s->requests_lock);
1070
static int coroutine_fn
1071
nbd_co_receive_return_code(BDRVNBDState *s, uint64_t cookie,
1072
int *request_ret, Error **errp)
1074
NBDReplyChunkIter iter;
1076
NBD_FOREACH_REPLY_CHUNK(s, iter, cookie, false, NULL, NULL, NULL) {
1080
error_propagate(errp, iter.err);
1081
*request_ret = iter.request_ret;
1085
static int coroutine_fn
1086
nbd_co_receive_cmdread_reply(BDRVNBDState *s, uint64_t cookie,
1087
uint64_t offset, QEMUIOVector *qiov,
1088
int *request_ret, Error **errp)
1090
NBDReplyChunkIter iter;
1092
void *payload = NULL;
1093
Error *local_err = NULL;
1095
NBD_FOREACH_REPLY_CHUNK(s, iter, cookie,
1096
s->info.mode >= NBD_MODE_STRUCTURED,
1097
qiov, &reply, &payload)
1100
NBDStructuredReplyChunk *chunk = &reply.structured;
1102
assert(nbd_reply_is_structured(&reply));
1104
switch (chunk->type) {
1105
case NBD_REPLY_TYPE_OFFSET_DATA:
1111
case NBD_REPLY_TYPE_OFFSET_HOLE:
1112
ret = nbd_parse_offset_hole_payload(s, &reply.structured, payload,
1113
offset, qiov, &local_err);
1115
nbd_channel_error(s, ret);
1116
nbd_iter_channel_error(&iter, ret, &local_err);
1120
if (!nbd_reply_type_is_error(chunk->type)) {
1122
nbd_channel_error(s, -EINVAL);
1123
error_setg(&local_err,
1124
"Unexpected reply type: %d (%s) for CMD_READ",
1125
chunk->type, nbd_reply_type_lookup(chunk->type));
1126
nbd_iter_channel_error(&iter, -EINVAL, &local_err);
1134
error_propagate(errp, iter.err);
1135
*request_ret = iter.request_ret;
1139
static int coroutine_fn
1140
nbd_co_receive_blockstatus_reply(BDRVNBDState *s, uint64_t cookie,
1141
uint64_t length, NBDExtent64 *extent,
1142
int *request_ret, Error **errp)
1144
NBDReplyChunkIter iter;
1146
void *payload = NULL;
1147
Error *local_err = NULL;
1148
bool received = false;
1150
assert(!extent->length);
1151
NBD_FOREACH_REPLY_CHUNK(s, iter, cookie, false, NULL, &reply, &payload) {
1153
NBDStructuredReplyChunk *chunk = &reply.structured;
1156
assert(nbd_reply_is_structured(&reply));
1158
switch (chunk->type) {
1159
case NBD_REPLY_TYPE_BLOCK_STATUS_EXT:
1160
case NBD_REPLY_TYPE_BLOCK_STATUS:
1161
wide = chunk->type == NBD_REPLY_TYPE_BLOCK_STATUS_EXT;
1162
if ((s->info.mode >= NBD_MODE_EXTENDED) != wide) {
1163
trace_nbd_extended_headers_compliance("block_status");
1166
nbd_channel_error(s, -EINVAL);
1167
error_setg(&local_err, "Several BLOCK_STATUS chunks in reply");
1168
nbd_iter_channel_error(&iter, -EINVAL, &local_err);
1172
ret = nbd_parse_blockstatus_payload(
1173
s, &reply.structured, payload, wide,
1174
length, extent, &local_err);
1176
nbd_channel_error(s, ret);
1177
nbd_iter_channel_error(&iter, ret, &local_err);
1181
if (!nbd_reply_type_is_error(chunk->type)) {
1182
nbd_channel_error(s, -EINVAL);
1183
error_setg(&local_err,
1184
"Unexpected reply type: %d (%s) "
1185
"for CMD_BLOCK_STATUS",
1186
chunk->type, nbd_reply_type_lookup(chunk->type));
1187
nbd_iter_channel_error(&iter, -EINVAL, &local_err);
1195
if (!extent->length && !iter.request_ret) {
1196
error_setg(&local_err, "Server did not reply with any status extents");
1197
nbd_iter_channel_error(&iter, -EIO, &local_err);
1200
error_propagate(errp, iter.err);
1201
*request_ret = iter.request_ret;
1205
static int coroutine_fn GRAPH_RDLOCK
1206
nbd_co_request(BlockDriverState *bs, NBDRequest *request,
1207
QEMUIOVector *write_qiov)
1209
int ret, request_ret;
1210
Error *local_err = NULL;
1211
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1213
assert(request->type != NBD_CMD_READ);
1215
assert(request->type == NBD_CMD_WRITE);
1216
assert(request->len == iov_size(write_qiov->iov, write_qiov->niov));
1218
assert(request->type != NBD_CMD_WRITE);
1222
ret = nbd_co_send_request(bs, request, write_qiov);
1227
ret = nbd_co_receive_return_code(s, request->cookie,
1228
&request_ret, &local_err);
1230
trace_nbd_co_request_fail(request->from, request->len,
1231
request->cookie, request->flags,
1233
nbd_cmd_lookup(request->type),
1234
ret, error_get_pretty(local_err));
1235
error_free(local_err);
1238
} while (ret < 0 && nbd_client_will_reconnect(s));
1240
return ret ? ret : request_ret;
1243
static int coroutine_fn GRAPH_RDLOCK
1244
nbd_client_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1245
QEMUIOVector *qiov, BdrvRequestFlags flags)
1247
int ret, request_ret;
1248
Error *local_err = NULL;
1249
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1250
NBDRequest request = {
1251
.type = NBD_CMD_READ,
1256
assert(bytes <= NBD_MAX_BUFFER_SIZE);
1267
if (offset >= s->info.size) {
1268
assert(bytes < BDRV_SECTOR_SIZE);
1269
qemu_iovec_memset(qiov, 0, 0, bytes);
1272
if (offset + bytes > s->info.size) {
1273
uint64_t slop = offset + bytes - s->info.size;
1275
assert(slop < BDRV_SECTOR_SIZE);
1276
qemu_iovec_memset(qiov, bytes - slop, 0, slop);
1277
request.len -= slop;
1281
ret = nbd_co_send_request(bs, &request, NULL);
1286
ret = nbd_co_receive_cmdread_reply(s, request.cookie, offset, qiov,
1287
&request_ret, &local_err);
1289
trace_nbd_co_request_fail(request.from, request.len, request.cookie,
1290
request.flags, request.type,
1291
nbd_cmd_lookup(request.type),
1292
ret, error_get_pretty(local_err));
1293
error_free(local_err);
1296
} while (ret < 0 && nbd_client_will_reconnect(s));
1298
return ret ? ret : request_ret;
1301
static int coroutine_fn GRAPH_RDLOCK
1302
nbd_client_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1303
QEMUIOVector *qiov, BdrvRequestFlags flags)
1305
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1306
NBDRequest request = {
1307
.type = NBD_CMD_WRITE,
1312
assert(!(s->info.flags & NBD_FLAG_READ_ONLY));
1313
if (flags & BDRV_REQ_FUA) {
1314
assert(s->info.flags & NBD_FLAG_SEND_FUA);
1315
request.flags |= NBD_CMD_FLAG_FUA;
1318
assert(bytes <= NBD_MAX_BUFFER_SIZE);
1323
return nbd_co_request(bs, &request, qiov);
1326
static int coroutine_fn GRAPH_RDLOCK
1327
nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
1328
BdrvRequestFlags flags)
1330
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1331
NBDRequest request = {
1332
.type = NBD_CMD_WRITE_ZEROES,
1338
assert(bytes <= UINT32_MAX || s->info.mode >= NBD_MODE_EXTENDED);
1340
assert(!(s->info.flags & NBD_FLAG_READ_ONLY));
1341
if (!(s->info.flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
1345
if (flags & BDRV_REQ_FUA) {
1346
assert(s->info.flags & NBD_FLAG_SEND_FUA);
1347
request.flags |= NBD_CMD_FLAG_FUA;
1349
if (!(flags & BDRV_REQ_MAY_UNMAP)) {
1350
request.flags |= NBD_CMD_FLAG_NO_HOLE;
1352
if (flags & BDRV_REQ_NO_FALLBACK) {
1353
assert(s->info.flags & NBD_FLAG_SEND_FAST_ZERO);
1354
request.flags |= NBD_CMD_FLAG_FAST_ZERO;
1360
return nbd_co_request(bs, &request, NULL);
1363
static int coroutine_fn GRAPH_RDLOCK nbd_client_co_flush(BlockDriverState *bs)
1365
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1366
NBDRequest request = { .type = NBD_CMD_FLUSH };
1368
if (!(s->info.flags & NBD_FLAG_SEND_FLUSH)) {
1375
return nbd_co_request(bs, &request, NULL);
1378
static int coroutine_fn GRAPH_RDLOCK
1379
nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
1381
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1382
NBDRequest request = {
1383
.type = NBD_CMD_TRIM,
1389
assert(bytes <= UINT32_MAX || s->info.mode >= NBD_MODE_EXTENDED);
1391
assert(!(s->info.flags & NBD_FLAG_READ_ONLY));
1392
if (!(s->info.flags & NBD_FLAG_SEND_TRIM) || !bytes) {
1396
return nbd_co_request(bs, &request, NULL);
1399
static int coroutine_fn GRAPH_RDLOCK nbd_client_co_block_status(
1400
BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
1401
int64_t *pnum, int64_t *map, BlockDriverState **file)
1403
int ret, request_ret;
1404
NBDExtent64 extent = { 0 };
1405
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1406
Error *local_err = NULL;
1408
NBDRequest request = {
1409
.type = NBD_CMD_BLOCK_STATUS,
1411
.len = MIN(bytes, s->info.size - offset),
1412
.flags = NBD_CMD_FLAG_REQ_ONE,
1415
if (!s->info.base_allocation) {
1419
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
1421
if (s->info.mode < NBD_MODE_EXTENDED) {
1422
request.len = MIN(QEMU_ALIGN_DOWN(INT_MAX, bs->bl.request_alignment),
1433
if (offset >= s->info.size) {
1435
assert(bytes < BDRV_SECTOR_SIZE);
1437
return BDRV_BLOCK_ZERO;
1440
if (s->info.min_block) {
1441
assert(QEMU_IS_ALIGNED(request.len, s->info.min_block));
1444
ret = nbd_co_send_request(bs, &request, NULL);
1449
ret = nbd_co_receive_blockstatus_reply(s, request.cookie, bytes,
1450
&extent, &request_ret,
1453
trace_nbd_co_request_fail(request.from, request.len, request.cookie,
1454
request.flags, request.type,
1455
nbd_cmd_lookup(request.type),
1456
ret, error_get_pretty(local_err));
1457
error_free(local_err);
1460
} while (ret < 0 && nbd_client_will_reconnect(s));
1462
if (ret < 0 || request_ret < 0) {
1463
return ret ? ret : request_ret;
1466
assert(extent.length);
1467
*pnum = extent.length;
1470
return (extent.flags & NBD_STATE_HOLE ? 0 : BDRV_BLOCK_DATA) |
1471
(extent.flags & NBD_STATE_ZERO ? BDRV_BLOCK_ZERO : 0) |
1472
BDRV_BLOCK_OFFSET_VALID;
1475
static int nbd_client_reopen_prepare(BDRVReopenState *state,
1476
BlockReopenQueue *queue, Error **errp)
1478
BDRVNBDState *s = (BDRVNBDState *)state->bs->opaque;
1480
if ((state->flags & BDRV_O_RDWR) && (s->info.flags & NBD_FLAG_READ_ONLY)) {
1481
error_setg(errp, "Can't reopen read-only NBD mount as read/write");
1487
static void nbd_yank(void *opaque)
1489
BlockDriverState *bs = opaque;
1490
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1492
QEMU_LOCK_GUARD(&s->requests_lock);
1493
qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
1494
s->state = NBD_CLIENT_QUIT;
1497
static void nbd_client_close(BlockDriverState *bs)
1499
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1500
NBDRequest request = { .type = NBD_CMD_DISC, .mode = s->info.mode };
1503
nbd_send_request(s->ioc, &request);
1506
nbd_teardown_connection(bs);
1514
static int nbd_parse_uri(const char *filename, QDict *options)
1516
g_autoptr(GUri) uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
1517
g_autoptr(GHashTable) qp = NULL;
1521
const char *uri_scheme, *uri_query, *uri_server;
1529
uri_scheme = g_uri_get_scheme(uri);
1530
if (!g_strcmp0(uri_scheme, "nbd")) {
1532
} else if (!g_strcmp0(uri_scheme, "nbd+tcp")) {
1534
} else if (!g_strcmp0(uri_scheme, "nbd+unix")) {
1540
p = g_uri_get_path(uri) ?: "";
1545
qdict_put_str(options, "export", p);
1548
uri_query = g_uri_get_query(uri);
1550
qp = g_uri_parse_params(uri_query, -1, "&", G_URI_PARAMS_NONE, NULL);
1554
qp_n = g_hash_table_size(qp);
1555
if (qp_n > 1 || (is_unix && !qp_n) || (!is_unix && qp_n)) {
1560
uri_server = g_uri_get_host(uri);
1561
if (uri_server && !uri_server[0]) {
1564
uri_port = g_uri_get_port(uri);
1568
const char *uri_socket = g_hash_table_lookup(qp, "socket");
1569
if (uri_server || uri_port != -1 || !uri_socket) {
1572
qdict_put_str(options, "server.type", "unix");
1573
qdict_put_str(options, "server.path", uri_socket);
1582
qdict_put_str(options, "server.type", "inet");
1583
qdict_put_str(options, "server.host", uri_server);
1585
port_str = g_strdup_printf("%d", uri_port > 0 ? uri_port
1586
: NBD_DEFAULT_PORT);
1587
qdict_put_str(options, "server.port", port_str);
1594
static bool nbd_has_filename_options_conflict(QDict *options, Error **errp)
1596
const QDictEntry *e;
1598
for (e = qdict_first(options); e; e = qdict_next(options, e)) {
1599
if (!strcmp(e->key, "host") ||
1600
!strcmp(e->key, "port") ||
1601
!strcmp(e->key, "path") ||
1602
!strcmp(e->key, "export") ||
1603
strstart(e->key, "server.", NULL))
1605
error_setg(errp, "Option '%s' cannot be used with a file name",
1614
static void nbd_parse_filename(const char *filename, QDict *options,
1617
g_autofree char *file = NULL;
1619
const char *host_spec;
1620
const char *unixpath;
1622
if (nbd_has_filename_options_conflict(options, errp)) {
1626
if (strstr(filename, "://")) {
1627
int ret = nbd_parse_uri(filename, options);
1629
error_setg(errp, "No valid URL specified");
1634
file = g_strdup(filename);
1636
export_name = strstr(file, EN_OPTSTR);
1638
if (export_name[strlen(EN_OPTSTR)] == 0) {
1642
export_name += strlen(EN_OPTSTR);
1644
qdict_put_str(options, "export", export_name);
1648
if (!strstart(file, "nbd:", &host_spec)) {
1649
error_setg(errp, "File name string for NBD must start with 'nbd:'");
1658
if (strstart(host_spec, "unix:", &unixpath)) {
1659
qdict_put_str(options, "server.type", "unix");
1660
qdict_put_str(options, "server.path", unixpath);
1662
InetSocketAddress *addr = g_new(InetSocketAddress, 1);
1664
if (inet_parse(addr, host_spec, errp)) {
1668
qdict_put_str(options, "server.type", "inet");
1669
qdict_put_str(options, "server.host", addr->host);
1670
qdict_put_str(options, "server.port", addr->port);
1672
qapi_free_InetSocketAddress(addr);
1676
static bool nbd_process_legacy_socket_options(QDict *output_options,
1677
QemuOpts *legacy_opts,
1680
const char *path = qemu_opt_get(legacy_opts, "path");
1681
const char *host = qemu_opt_get(legacy_opts, "host");
1682
const char *port = qemu_opt_get(legacy_opts, "port");
1683
const QDictEntry *e;
1685
if (!path && !host && !port) {
1689
for (e = qdict_first(output_options); e; e = qdict_next(output_options, e))
1691
if (strstart(e->key, "server.", NULL)) {
1692
error_setg(errp, "Cannot use 'server' and path/host/port at the "
1699
error_setg(errp, "path and host may not be used at the same time");
1703
error_setg(errp, "port may not be used without host");
1707
qdict_put_str(output_options, "server.type", "unix");
1708
qdict_put_str(output_options, "server.path", path);
1710
qdict_put_str(output_options, "server.type", "inet");
1711
qdict_put_str(output_options, "server.host", host);
1712
qdict_put_str(output_options, "server.port",
1713
port ?: stringify(NBD_DEFAULT_PORT));
1719
static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options,
1722
SocketAddress *saddr = NULL;
1726
qdict_extract_subqdict(options, &addr, "server.");
1727
if (!qdict_size(addr)) {
1728
error_setg(errp, "NBD server address missing");
1732
iv = qobject_input_visitor_new_flat_confused(addr, errp);
1737
if (!visit_type_SocketAddress(iv, NULL, &saddr, errp)) {
1741
if (socket_address_parse_named_fd(saddr, errp) < 0) {
1742
qapi_free_SocketAddress(saddr);
1748
qobject_unref(addr);
1753
static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
1756
QCryptoTLSCreds *creds;
1758
obj = object_resolve_path_component(
1759
object_get_objects_root(), id);
1761
error_setg(errp, "No TLS credentials with id '%s'",
1765
creds = (QCryptoTLSCreds *)
1766
object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS);
1768
error_setg(errp, "Object with id '%s' is not TLS credentials",
1773
if (!qcrypto_tls_creds_check_endpoint(creds,
1774
QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
1783
static QemuOptsList nbd_runtime_opts = {
1785
.head = QTAILQ_HEAD_INITIALIZER(nbd_runtime_opts.head),
1789
.type = QEMU_OPT_STRING,
1790
.help = "TCP host to connect to",
1794
.type = QEMU_OPT_STRING,
1795
.help = "TCP port to connect to",
1799
.type = QEMU_OPT_STRING,
1800
.help = "Unix socket path to connect to",
1804
.type = QEMU_OPT_STRING,
1805
.help = "Name of the NBD export to open",
1808
.name = "tls-creds",
1809
.type = QEMU_OPT_STRING,
1810
.help = "ID of the TLS credentials to use",
1813
.name = "tls-hostname",
1814
.type = QEMU_OPT_STRING,
1815
.help = "Override hostname for validating TLS x509 certificate",
1818
.name = "x-dirty-bitmap",
1819
.type = QEMU_OPT_STRING,
1820
.help = "experimental: expose named dirty bitmap in place of "
1824
.name = "reconnect-delay",
1825
.type = QEMU_OPT_NUMBER,
1826
.help = "On an unexpected disconnect, the nbd client tries to "
1827
"connect again until succeeding or encountering a serious "
1828
"error. During the first @reconnect-delay seconds, all "
1829
"requests are paused and will be rerun on a successful "
1830
"reconnect. After that time, any delayed requests and all "
1831
"future requests before a successful reconnect will "
1832
"immediately fail. Default 0",
1835
.name = "open-timeout",
1836
.type = QEMU_OPT_NUMBER,
1837
.help = "In seconds. If zero, the nbd driver tries the connection "
1838
"only once, and fails to open if the connection fails. "
1839
"If non-zero, the nbd driver will repeat connection "
1840
"attempts until successful or until @open-timeout seconds "
1841
"have elapsed. Default 0",
1847
static int nbd_process_options(BlockDriverState *bs, QDict *options,
1850
BDRVNBDState *s = bs->opaque;
1854
opts = qemu_opts_create(&nbd_runtime_opts, NULL, 0, &error_abort);
1855
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
1860
if (!nbd_process_legacy_socket_options(options, opts, errp)) {
1865
s->saddr = nbd_config(s, options, errp);
1870
s->export = g_strdup(qemu_opt_get(opts, "export"));
1871
if (s->export && strlen(s->export) > NBD_MAX_STRING_SIZE) {
1872
error_setg(errp, "export name too long to send to server");
1876
s->tlscredsid = g_strdup(qemu_opt_get(opts, "tls-creds"));
1877
if (s->tlscredsid) {
1878
s->tlscreds = nbd_get_tls_creds(s->tlscredsid, errp);
1883
s->tlshostname = g_strdup(qemu_opt_get(opts, "tls-hostname"));
1884
if (!s->tlshostname &&
1885
s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
1886
s->tlshostname = g_strdup(s->saddr->u.inet.host);
1890
s->x_dirty_bitmap = g_strdup(qemu_opt_get(opts, "x-dirty-bitmap"));
1891
if (s->x_dirty_bitmap && strlen(s->x_dirty_bitmap) > NBD_MAX_STRING_SIZE) {
1892
error_setg(errp, "x-dirty-bitmap query too long to send to server");
1896
s->reconnect_delay = qemu_opt_get_number(opts, "reconnect-delay", 0);
1897
s->open_timeout = qemu_opt_get_number(opts, "open-timeout", 0);
1902
qemu_opts_del(opts);
1906
static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
1910
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1913
qemu_mutex_init(&s->requests_lock);
1914
qemu_co_queue_init(&s->free_sema);
1915
qemu_co_mutex_init(&s->send_mutex);
1916
qemu_co_mutex_init(&s->receive_mutex);
1918
if (!yank_register_instance(BLOCKDEV_YANK_INSTANCE(bs->node_name), errp)) {
1922
ret = nbd_process_options(bs, options, errp);
1927
s->conn = nbd_client_connection_new(s->saddr, true, s->export,
1928
s->x_dirty_bitmap, s->tlscreds,
1931
if (s->open_timeout) {
1932
nbd_client_connection_enable_retry(s->conn);
1933
open_timer_init(s, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) +
1934
s->open_timeout * NANOSECONDS_PER_SECOND);
1937
s->state = NBD_CLIENT_CONNECTING_WAIT;
1938
ret = nbd_do_establish_connection(bs, true, errp);
1950
nbd_client_connection_enable_retry(s->conn);
1956
nbd_clear_bdrvstate(bs);
1960
static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
1962
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
1963
uint32_t min = s->info.min_block;
1964
uint32_t max = MIN_NON_ZERO(NBD_MAX_BUFFER_SIZE, s->info.max_block);
1979
min = (!QEMU_IS_ALIGNED(s->info.size, BDRV_SECTOR_SIZE) ||
1980
s->info.base_allocation) ? 1 : BDRV_SECTOR_SIZE;
1983
bs->bl.request_alignment = min;
1984
bs->bl.max_pdiscard = QEMU_ALIGN_DOWN(INT_MAX, min);
1985
bs->bl.max_pwrite_zeroes = max;
1986
bs->bl.max_transfer = max;
1992
if (s->info.mode >= NBD_MODE_EXTENDED) {
1993
bs->bl.max_pdiscard = bs->bl.max_pwrite_zeroes = 0;
1996
if (s->info.opt_block &&
1997
s->info.opt_block > bs->bl.opt_transfer) {
1998
bs->bl.opt_transfer = s->info.opt_block;
2002
static void nbd_close(BlockDriverState *bs)
2004
nbd_client_close(bs);
2005
nbd_clear_bdrvstate(bs);
2016
static int coroutine_fn nbd_co_truncate(BlockDriverState *bs, int64_t offset,
2017
bool exact, PreallocMode prealloc,
2018
BdrvRequestFlags flags, Error **errp)
2020
BDRVNBDState *s = bs->opaque;
2022
if (offset != s->info.size && exact) {
2023
error_setg(errp, "Cannot resize NBD nodes");
2027
if (offset > s->info.size) {
2028
error_setg(errp, "Cannot grow NBD nodes");
2035
static int64_t coroutine_fn nbd_co_getlength(BlockDriverState *bs)
2037
BDRVNBDState *s = bs->opaque;
2039
return s->info.size;
2042
static void nbd_refresh_filename(BlockDriverState *bs)
2044
BDRVNBDState *s = bs->opaque;
2045
const char *host = NULL, *port = NULL, *path = NULL;
2048
if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
2049
const InetSocketAddress *inet = &s->saddr->u.inet;
2050
if (!inet->has_ipv4 && !inet->has_ipv6 && !inet->has_to) {
2054
} else if (s->saddr->type == SOCKET_ADDRESS_TYPE_UNIX) {
2055
path = s->saddr->u.q_unix.path;
2058
if (path && s->export) {
2059
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
2060
"nbd+unix:///%s?socket=%s", s->export, path);
2061
} else if (path && !s->export) {
2062
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
2063
"nbd+unix://?socket=%s", path);
2064
} else if (host && s->export) {
2065
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
2066
"nbd://%s:%s/%s", host, port, s->export);
2067
} else if (host && !s->export) {
2068
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
2069
"nbd://%s:%s", host, port);
2071
if (len >= sizeof(bs->exact_filename)) {
2073
bs->exact_filename[0] = '\0';
2077
static char *nbd_dirname(BlockDriverState *bs, Error **errp)
2083
error_setg(errp, "Cannot generate a base directory for NBD nodes");
2087
static const char *const nbd_strong_runtime_opts[] = {
2099
static void nbd_cancel_in_flight(BlockDriverState *bs)
2101
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
2103
reconnect_delay_timer_del(s);
2105
qemu_mutex_lock(&s->requests_lock);
2106
if (s->state == NBD_CLIENT_CONNECTING_WAIT) {
2107
s->state = NBD_CLIENT_CONNECTING_NOWAIT;
2109
qemu_mutex_unlock(&s->requests_lock);
2111
nbd_co_establish_connection_cancel(s->conn);
2114
static void nbd_attach_aio_context(BlockDriverState *bs,
2115
AioContext *new_context)
2117
BDRVNBDState *s = bs->opaque;
2120
assert(!s->open_timer);
2131
assert(!s->reconnect_delay_timer);
2134
static void nbd_detach_aio_context(BlockDriverState *bs)
2136
BDRVNBDState *s = bs->opaque;
2138
assert(!s->open_timer);
2139
assert(!s->reconnect_delay_timer);
2142
static BlockDriver bdrv_nbd = {
2143
.format_name = "nbd",
2144
.protocol_name = "nbd",
2145
.instance_size = sizeof(BDRVNBDState),
2146
.bdrv_parse_filename = nbd_parse_filename,
2147
.bdrv_co_create_opts = bdrv_co_create_opts_simple,
2148
.create_opts = &bdrv_create_opts_simple,
2149
.bdrv_open = nbd_open,
2150
.bdrv_reopen_prepare = nbd_client_reopen_prepare,
2151
.bdrv_co_preadv = nbd_client_co_preadv,
2152
.bdrv_co_pwritev = nbd_client_co_pwritev,
2153
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
2154
.bdrv_close = nbd_close,
2155
.bdrv_co_flush_to_os = nbd_client_co_flush,
2156
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
2157
.bdrv_refresh_limits = nbd_refresh_limits,
2158
.bdrv_co_truncate = nbd_co_truncate,
2159
.bdrv_co_getlength = nbd_co_getlength,
2160
.bdrv_refresh_filename = nbd_refresh_filename,
2161
.bdrv_co_block_status = nbd_client_co_block_status,
2162
.bdrv_dirname = nbd_dirname,
2163
.strong_runtime_opts = nbd_strong_runtime_opts,
2164
.bdrv_cancel_in_flight = nbd_cancel_in_flight,
2166
.bdrv_attach_aio_context = nbd_attach_aio_context,
2167
.bdrv_detach_aio_context = nbd_detach_aio_context,
2170
static BlockDriver bdrv_nbd_tcp = {
2171
.format_name = "nbd",
2172
.protocol_name = "nbd+tcp",
2173
.instance_size = sizeof(BDRVNBDState),
2174
.bdrv_parse_filename = nbd_parse_filename,
2175
.bdrv_co_create_opts = bdrv_co_create_opts_simple,
2176
.create_opts = &bdrv_create_opts_simple,
2177
.bdrv_open = nbd_open,
2178
.bdrv_reopen_prepare = nbd_client_reopen_prepare,
2179
.bdrv_co_preadv = nbd_client_co_preadv,
2180
.bdrv_co_pwritev = nbd_client_co_pwritev,
2181
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
2182
.bdrv_close = nbd_close,
2183
.bdrv_co_flush_to_os = nbd_client_co_flush,
2184
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
2185
.bdrv_refresh_limits = nbd_refresh_limits,
2186
.bdrv_co_truncate = nbd_co_truncate,
2187
.bdrv_co_getlength = nbd_co_getlength,
2188
.bdrv_refresh_filename = nbd_refresh_filename,
2189
.bdrv_co_block_status = nbd_client_co_block_status,
2190
.bdrv_dirname = nbd_dirname,
2191
.strong_runtime_opts = nbd_strong_runtime_opts,
2192
.bdrv_cancel_in_flight = nbd_cancel_in_flight,
2194
.bdrv_attach_aio_context = nbd_attach_aio_context,
2195
.bdrv_detach_aio_context = nbd_detach_aio_context,
2198
static BlockDriver bdrv_nbd_unix = {
2199
.format_name = "nbd",
2200
.protocol_name = "nbd+unix",
2201
.instance_size = sizeof(BDRVNBDState),
2202
.bdrv_parse_filename = nbd_parse_filename,
2203
.bdrv_co_create_opts = bdrv_co_create_opts_simple,
2204
.create_opts = &bdrv_create_opts_simple,
2205
.bdrv_open = nbd_open,
2206
.bdrv_reopen_prepare = nbd_client_reopen_prepare,
2207
.bdrv_co_preadv = nbd_client_co_preadv,
2208
.bdrv_co_pwritev = nbd_client_co_pwritev,
2209
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
2210
.bdrv_close = nbd_close,
2211
.bdrv_co_flush_to_os = nbd_client_co_flush,
2212
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
2213
.bdrv_refresh_limits = nbd_refresh_limits,
2214
.bdrv_co_truncate = nbd_co_truncate,
2215
.bdrv_co_getlength = nbd_co_getlength,
2216
.bdrv_refresh_filename = nbd_refresh_filename,
2217
.bdrv_co_block_status = nbd_client_co_block_status,
2218
.bdrv_dirname = nbd_dirname,
2219
.strong_runtime_opts = nbd_strong_runtime_opts,
2220
.bdrv_cancel_in_flight = nbd_cancel_in_flight,
2222
.bdrv_attach_aio_context = nbd_attach_aio_context,
2223
.bdrv_detach_aio_context = nbd_detach_aio_context,
2226
static void bdrv_nbd_init(void)
2228
bdrv_register(&bdrv_nbd);
2229
bdrv_register(&bdrv_nbd_tcp);
2230
bdrv_register(&bdrv_nbd_unix);
2233
block_init(bdrv_nbd_init);