65
67
Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
66
68
struct nbd_reply reply;
71
QemuOpts *socket_opts;
70
73
char *export_name; /* An NBD server may export several devices */
73
static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
76
static int nbd_parse_uri(const char *filename, QDict *options)
77
80
QueryParams *qp = NULL;
80
84
uri = uri_parse(filename);
97
101
p = uri->path ? uri->path : "/";
98
102
p += strspn(p, "/");
100
s->export_name = g_strdup(p);
104
qdict_put(options, "export", qstring_from_str(p));
103
107
qp = query_params_parse(uri->query);
104
if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
108
if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
110
114
/* nbd+unix:///export?socket=path */
111
115
if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
115
s->host_spec = g_strdup(qp->p[0].value);
119
qdict_put(options, "path", qstring_from_str(qp->p[0].value));
117
/* nbd[+tcp]://host:port/export */
121
/* nbd[+tcp]://host[:port]/export */
118
122
if (!uri->server) {
123
uri->port = NBD_DEFAULT_PORT;
127
qdict_put(options, "host", qstring_from_str(uri->server));
129
char* port_str = g_strdup_printf("%d", uri->port);
130
qdict_put(options, "port", qstring_from_str(port_str));
125
s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);
136
static int nbd_config(BDRVNBDState *s, const char *filename)
143
static void nbd_parse_filename(const char *filename, QDict *options,
139
147
char *export_name;
140
148
const char *host_spec;
141
149
const char *unixpath;
151
if (qdict_haskey(options, "host")
152
|| qdict_haskey(options, "port")
153
|| qdict_haskey(options, "path"))
155
error_setg(errp, "host/port/path and a file name may not be specified "
144
160
if (strstr(filename, "://")) {
145
return nbd_parse_uri(s, filename);
161
int ret = nbd_parse_uri(filename, options);
163
error_setg(errp, "No valid URL specified");
148
168
file = g_strdup(filename);
155
175
export_name[0] = 0; /* truncate 'file' */
156
176
export_name += strlen(EN_OPTSTR);
157
s->export_name = g_strdup(export_name);
178
qdict_put(options, "export", qstring_from_str(export_name));
160
181
/* extract the host_spec - fail if it's not nbd:... */
161
182
if (!strstart(file, "nbd:", &host_spec)) {
183
error_setg(errp, "File name string for NBD must start with 'nbd:'");
165
191
/* are we a UNIX or TCP socket? */
166
192
if (strstart(host_spec, "unix:", &unixpath)) {
168
s->host_spec = g_strdup(unixpath);
193
qdict_put(options, "path", qstring_from_str(unixpath));
171
s->host_spec = g_strdup(host_spec);
195
InetSocketAddress *addr = NULL;
197
addr = inet_parse(host_spec, errp);
198
if (error_is_set(errp)) {
202
qdict_put(options, "host", qstring_from_str(addr->host));
203
qdict_put(options, "port", qstring_from_str(addr->port));
204
qapi_free_InetSocketAddress(addr);
179
g_free(s->export_name);
180
g_free(s->host_spec);
211
static int nbd_config(BDRVNBDState *s, QDict *options)
213
Error *local_err = NULL;
215
if (qdict_haskey(options, "path")) {
216
if (qdict_haskey(options, "host")) {
217
qerror_report(ERROR_CLASS_GENERIC_ERROR, "path and host may not "
218
"be used at the same time.");
222
} else if (qdict_haskey(options, "host")) {
228
s->socket_opts = qemu_opts_create_nofail(&socket_optslist);
230
qemu_opts_absorb_qdict(s->socket_opts, options, &local_err);
231
if (error_is_set(&local_err)) {
232
qerror_report_err(local_err);
233
error_free(local_err);
237
if (!qemu_opt_get(s->socket_opts, "port")) {
238
qemu_opt_set_number(s->socket_opts, "port", NBD_DEFAULT_PORT);
241
s->export_name = g_strdup(qdict_get_try_str(options, "export"));
242
if (s->export_name) {
243
qdict_del(options, "export");
185
250
static void nbd_coroutine_start(BDRVNBDState *s, struct nbd_request *request)
269
334
s->send_coroutine = qemu_coroutine_self();
270
335
qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write,
271
336
nbd_have_request, s);
272
rc = nbd_send_request(s->sock, request);
273
if (rc >= 0 && qiov) {
274
ret = qemu_co_sendv(s->sock, qiov->iov, qiov->niov,
275
offset, request->len);
276
if (ret != request->len) {
339
socket_set_cork(s->sock, 1);
341
rc = nbd_send_request(s->sock, request);
343
ret = qemu_co_sendv(s->sock, qiov->iov, qiov->niov,
344
offset, request->len);
345
if (ret != request->len) {
350
socket_set_cork(s->sock, 0);
353
rc = nbd_send_request(s->sock, request);
280
355
qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL,
281
356
nbd_have_request, s);
328
403
size_t blocksize;
330
405
if (s->is_unix) {
331
sock = unix_socket_outgoing(s->host_spec);
406
sock = unix_socket_outgoing(qemu_opt_get(s->socket_opts, "path"));
333
sock = tcp_socket_outgoing_spec(s->host_spec);
408
sock = tcp_socket_outgoing_opts(s->socket_opts);
410
socket_set_nodelay(sock);
336
414
/* Failed to establish connection */
351
429
/* Now that we're connected, set the socket to be non-blocking and
352
430
* kick the reply mechanism. */
353
socket_set_nonblock(sock);
431
qemu_set_nonblock(sock);
354
432
qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
355
433
nbd_have_request, s);
565
643
.format_name = "nbd",
566
644
.protocol_name = "nbd",
567
645
.instance_size = sizeof(BDRVNBDState),
646
.bdrv_parse_filename = nbd_parse_filename,
568
647
.bdrv_file_open = nbd_open,
569
648
.bdrv_co_readv = nbd_co_readv,
570
649
.bdrv_co_writev = nbd_co_writev,
578
657
.format_name = "nbd",
579
658
.protocol_name = "nbd+tcp",
580
659
.instance_size = sizeof(BDRVNBDState),
660
.bdrv_parse_filename = nbd_parse_filename,
581
661
.bdrv_file_open = nbd_open,
582
662
.bdrv_co_readv = nbd_co_readv,
583
663
.bdrv_co_writev = nbd_co_writev,
591
671
.format_name = "nbd",
592
672
.protocol_name = "nbd+unix",
593
673
.instance_size = sizeof(BDRVNBDState),
674
.bdrv_parse_filename = nbd_parse_filename,
594
675
.bdrv_file_open = nbd_open,
595
676
.bdrv_co_readv = nbd_co_readv,
596
677
.bdrv_co_writev = nbd_co_writev,