Lines Matching full:client

40  * recommends no larger than 32 mb, so that the client won't consider
83 NBDClient *client; member
126 void (*close_fn)(NBDClient *client, bool negotiated);
150 uint32_t check_align; /* If non-zero, check for aligned client requests */
160 static void nbd_client_receive_next_request(NBDClient *client);
164 Server Client
169 Server Client
178 Server Client
201 nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type, in nbd_negotiate_send_rep_len() argument
206 trace_nbd_negotiate_send_rep_len(client->opt, nbd_opt_lookup(client->opt), in nbd_negotiate_send_rep_len()
211 set_be_option_rep(&rep, client->opt, type, len); in nbd_negotiate_send_rep_len()
212 return nbd_write(client->ioc, &rep, sizeof(rep), errp); in nbd_negotiate_send_rep_len()
218 nbd_negotiate_send_rep(NBDClient *client, uint32_t type, Error **errp) in nbd_negotiate_send_rep() argument
220 return nbd_negotiate_send_rep_len(client, type, 0, errp); in nbd_negotiate_send_rep()
226 nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type, in nbd_negotiate_send_rep_verr() argument
238 ret = nbd_negotiate_send_rep_len(client, type, len, errp); in nbd_negotiate_send_rep_verr()
242 if (nbd_write(client->ioc, msg, len, errp) < 0) { in nbd_negotiate_send_rep_verr()
266 nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type, in nbd_negotiate_send_rep_err() argument
273 ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va); in nbd_negotiate_send_rep_err()
282 nbd_opt_vdrop(NBDClient *client, uint32_t type, Error **errp, in nbd_opt_vdrop() argument
285 int ret = nbd_drop(client->ioc, client->optlen, errp); in nbd_opt_vdrop()
287 client->optlen = 0; in nbd_opt_vdrop()
289 ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va); in nbd_opt_vdrop()
295 nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp, in nbd_opt_drop() argument
302 ret = nbd_opt_vdrop(client, type, errp, fmt, va); in nbd_opt_drop()
309 nbd_opt_invalid(NBDClient *client, Error **errp, const char *fmt, ...) in nbd_opt_invalid() argument
315 ret = nbd_opt_vdrop(client, NBD_REP_ERR_INVALID, errp, fmt, va); in nbd_opt_invalid()
326 nbd_opt_read(NBDClient *client, void *buffer, size_t size, in nbd_opt_read() argument
329 if (size > client->optlen) { in nbd_opt_read()
330 return nbd_opt_invalid(client, errp, in nbd_opt_read()
332 nbd_opt_lookup(client->opt)); in nbd_opt_read()
334 client->optlen -= size; in nbd_opt_read()
335 if (qio_channel_read_all(client->ioc, buffer, size, errp) < 0) { in nbd_opt_read()
340 return nbd_opt_invalid(client, errp, in nbd_opt_read()
342 nbd_opt_lookup(client->opt)); in nbd_opt_read()
351 nbd_opt_skip(NBDClient *client, size_t size, Error **errp) in nbd_opt_skip() argument
353 if (size > client->optlen) { in nbd_opt_skip()
354 return nbd_opt_invalid(client, errp, in nbd_opt_skip()
356 nbd_opt_lookup(client->opt)); in nbd_opt_skip()
358 client->optlen -= size; in nbd_opt_skip()
359 return nbd_drop(client->ioc, size, errp) < 0 ? -EIO : 1; in nbd_opt_skip()
375 nbd_opt_read_name(NBDClient *client, char **name, uint32_t *length, in nbd_opt_read_name() argument
383 ret = nbd_opt_read(client, &len, sizeof(len), false, errp); in nbd_opt_read_name()
390 return nbd_opt_invalid(client, errp, in nbd_opt_read_name()
395 ret = nbd_opt_read(client, local_name, len, true, errp); in nbd_opt_read_name()
412 nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp, Error **errp) in nbd_negotiate_send_rep_list() argument
419 QIOChannel *ioc = client->ioc; in nbd_negotiate_send_rep_list()
427 ret = nbd_negotiate_send_rep_len(client, NBD_REP_SERVER, len, errp); in nbd_negotiate_send_rep_list()
454 nbd_negotiate_handle_list(NBDClient *client, Error **errp) in nbd_negotiate_handle_list() argument
457 assert(client->opt == NBD_OPT_LIST); in nbd_negotiate_handle_list()
461 if (nbd_negotiate_send_rep_list(client, exp, errp)) { in nbd_negotiate_handle_list()
466 return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); in nbd_negotiate_handle_list()
470 nbd_check_meta_export(NBDClient *client, NBDExport *exp) in nbd_check_meta_export() argument
472 if (exp != client->contexts.exp) { in nbd_check_meta_export()
473 client->contexts.count = 0; in nbd_check_meta_export()
480 nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes, in nbd_negotiate_handle_export_name() argument
490 /* Client sends: in nbd_negotiate_handle_export_name()
498 if (client->mode >= NBD_MODE_EXTENDED) { in nbd_negotiate_handle_export_name()
502 if (client->optlen > NBD_MAX_STRING_SIZE) { in nbd_negotiate_handle_export_name()
506 name = g_malloc(client->optlen + 1); in nbd_negotiate_handle_export_name()
507 if (nbd_read(client->ioc, name, client->optlen, "export name", errp) < 0) { in nbd_negotiate_handle_export_name()
510 name[client->optlen] = '\0'; in nbd_negotiate_handle_export_name()
511 client->optlen = 0; in nbd_negotiate_handle_export_name()
515 client->exp = nbd_export_find(name); in nbd_negotiate_handle_export_name()
516 if (!client->exp) { in nbd_negotiate_handle_export_name()
520 nbd_check_meta_export(client, client->exp); in nbd_negotiate_handle_export_name()
522 myflags = client->exp->nbdflags; in nbd_negotiate_handle_export_name()
523 if (client->mode >= NBD_MODE_STRUCTURED) { in nbd_negotiate_handle_export_name()
526 if (client->mode >= NBD_MODE_EXTENDED && client->contexts.count) { in nbd_negotiate_handle_export_name()
529 trace_nbd_negotiate_new_style_size_flags(client->exp->size, myflags); in nbd_negotiate_handle_export_name()
530 stq_be_p(buf, client->exp->size); in nbd_negotiate_handle_export_name()
533 ret = nbd_write(client->ioc, buf, len, errp); in nbd_negotiate_handle_export_name()
539 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); in nbd_negotiate_handle_export_name()
540 blk_exp_ref(&client->exp->common); in nbd_negotiate_handle_export_name()
549 nbd_negotiate_send_info(NBDClient *client, uint16_t info, uint32_t length, in nbd_negotiate_send_info() argument
555 rc = nbd_negotiate_send_rep_len(client, NBD_REP_INFO, in nbd_negotiate_send_info()
561 if (nbd_write(client->ioc, &info, sizeof(info), errp) < 0) { in nbd_negotiate_send_info()
564 if (nbd_write(client->ioc, buf, length, errp) < 0) { in nbd_negotiate_send_info()
571 * @fatal requests that we quit talking to the client, even if we are able
575 * 0 error message successfully sent to client, errp is not set
578 nbd_reject_length(NBDClient *client, bool fatal, Error **errp) in nbd_reject_length() argument
582 assert(client->optlen); in nbd_reject_length()
583 ret = nbd_opt_invalid(client, errp, "option '%s' has unexpected length", in nbd_reject_length()
584 nbd_opt_lookup(client->opt)); in nbd_reject_length()
587 nbd_opt_lookup(client->opt)); in nbd_reject_length()
597 nbd_negotiate_handle_info(NBDClient *client, Error **errp) in nbd_negotiate_handle_info() argument
612 /* Client sends: in nbd_negotiate_handle_info()
618 rc = nbd_opt_read_name(client, &name, &namelen, errp); in nbd_negotiate_handle_info()
624 rc = nbd_opt_read(client, &requests, sizeof(requests), false, errp); in nbd_negotiate_handle_info()
631 rc = nbd_opt_read(client, &request, sizeof(request), false, errp); in nbd_negotiate_handle_info()
650 if (client->optlen) { in nbd_negotiate_handle_info()
651 return nbd_reject_length(client, false, errp); in nbd_negotiate_handle_info()
658 return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN, in nbd_negotiate_handle_info()
662 if (client->opt == NBD_OPT_GO) { in nbd_negotiate_handle_info()
663 nbd_check_meta_export(client, exp); in nbd_negotiate_handle_info()
666 /* Don't bother sending NBD_INFO_NAME unless client requested it */ in nbd_negotiate_handle_info()
668 rc = nbd_negotiate_send_info(client, NBD_INFO_NAME, namelen, name, in nbd_negotiate_handle_info()
676 * client request */ in nbd_negotiate_handle_info()
681 rc = nbd_negotiate_send_info(client, NBD_INFO_DESCRIPTION, in nbd_negotiate_handle_info()
689 * according to whether the client requested it, and according to in nbd_negotiate_handle_info()
691 /* minimum - 1 for back-compat, or actual if client will obey it. */ in nbd_negotiate_handle_info()
692 if (client->opt == NBD_OPT_INFO || blocksize) { in nbd_negotiate_handle_info()
707 rc = nbd_negotiate_send_info(client, NBD_INFO_BLOCK_SIZE, in nbd_negotiate_handle_info()
715 if (client->mode >= NBD_MODE_STRUCTURED) { in nbd_negotiate_handle_info()
718 if (client->mode >= NBD_MODE_EXTENDED && in nbd_negotiate_handle_info()
719 (client->contexts.count || client->opt == NBD_OPT_INFO)) { in nbd_negotiate_handle_info()
725 rc = nbd_negotiate_send_info(client, NBD_INFO_EXPORT, in nbd_negotiate_handle_info()
732 * If the client is just asking for NBD_OPT_INFO, but forgot to in nbd_negotiate_handle_info()
737 if (client->opt == NBD_OPT_INFO && !blocksize && in nbd_negotiate_handle_info()
739 return nbd_negotiate_send_rep_err(client, in nbd_negotiate_handle_info()
747 rc = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); in nbd_negotiate_handle_info()
752 if (client->opt == NBD_OPT_GO) { in nbd_negotiate_handle_info()
753 client->exp = exp; in nbd_negotiate_handle_info()
754 client->check_align = check_align; in nbd_negotiate_handle_info()
755 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); in nbd_negotiate_handle_info()
756 blk_exp_ref(&client->exp->common); in nbd_negotiate_handle_info()
784 nbd_negotiate_handle_starttls(NBDClient *client, Error **errp) in nbd_negotiate_handle_starttls() argument
790 assert(client->opt == NBD_OPT_STARTTLS); in nbd_negotiate_handle_starttls()
793 ioc = client->ioc; in nbd_negotiate_handle_starttls()
795 if (nbd_negotiate_send_rep(client, NBD_REP_ACK, errp) < 0) { in nbd_negotiate_handle_starttls()
800 client->tlscreds, in nbd_negotiate_handle_starttls()
801 client->tlsauthz, in nbd_negotiate_handle_starttls()
837 nbd_negotiate_send_meta_context(NBDClient *client, const char *context, in nbd_negotiate_send_meta_context() argument
847 if (client->opt == NBD_OPT_LIST_META_CONTEXT) { in nbd_negotiate_send_meta_context()
852 set_be_option_rep(&opt.h, client->opt, NBD_REP_META_CONTEXT, in nbd_negotiate_send_meta_context()
856 return qio_channel_writev_all(client->ioc, iov, 2, errp) < 0 ? -EIO : 0; in nbd_negotiate_send_meta_context()
861 * the @client is performing _LIST_.
864 nbd_meta_empty_or_pattern(NBDClient *client, const char *pattern, in nbd_meta_empty_or_pattern() argument
869 return client->opt == NBD_OPT_LIST_META_CONTEXT; in nbd_meta_empty_or_pattern()
900 nbd_meta_base_query(NBDClient *client, NBDMetaContexts *meta, in nbd_meta_base_query() argument
908 if (nbd_meta_empty_or_pattern(client, "allocation", query)) { in nbd_meta_base_query()
921 nbd_meta_qemu_query(NBDClient *client, NBDMetaContexts *meta, in nbd_meta_qemu_query() argument
932 if (client->opt == NBD_OPT_LIST_META_CONTEXT) { in nbd_meta_qemu_query()
951 if (client->opt == NBD_OPT_LIST_META_CONTEXT && in nbd_meta_qemu_query()
987 nbd_negotiate_meta_query(NBDClient *client, in nbd_negotiate_meta_query() argument
994 ret = nbd_opt_read(client, &len, sizeof(len), false, errp); in nbd_negotiate_meta_query()
1002 return nbd_opt_skip(client, len, errp); in nbd_negotiate_meta_query()
1006 ret = nbd_opt_read(client, query, len, true, errp); in nbd_negotiate_meta_query()
1012 if (nbd_meta_base_query(client, meta, query)) { in nbd_negotiate_meta_query()
1015 if (nbd_meta_qemu_query(client, meta, query)) { in nbd_negotiate_meta_query()
1028 nbd_negotiate_meta_queries(NBDClient *client, Error **errp) in nbd_negotiate_meta_queries() argument
1040 if (client->opt == NBD_OPT_SET_META_CONTEXT && in nbd_negotiate_meta_queries()
1041 client->mode < NBD_MODE_STRUCTURED) { in nbd_negotiate_meta_queries()
1042 return nbd_opt_invalid(client, errp, in nbd_negotiate_meta_queries()
1045 nbd_opt_lookup(client->opt)); in nbd_negotiate_meta_queries()
1048 if (client->opt == NBD_OPT_LIST_META_CONTEXT) { in nbd_negotiate_meta_queries()
1052 meta = &client->contexts; in nbd_negotiate_meta_queries()
1058 ret = nbd_opt_read_name(client, &export_name, NULL, errp); in nbd_negotiate_meta_queries()
1067 return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp, in nbd_negotiate_meta_queries()
1071 if (client->opt == NBD_OPT_LIST_META_CONTEXT) { in nbd_negotiate_meta_queries()
1075 ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), false, errp); in nbd_negotiate_meta_queries()
1080 trace_nbd_negotiate_meta_context(nbd_opt_lookup(client->opt), in nbd_negotiate_meta_queries()
1083 if (client->opt == NBD_OPT_LIST_META_CONTEXT && !nb_queries) { in nbd_negotiate_meta_queries()
1092 ret = nbd_negotiate_meta_query(client, meta, errp); in nbd_negotiate_meta_queries()
1100 ret = nbd_negotiate_send_meta_context(client, "base:allocation", in nbd_negotiate_meta_queries()
1110 ret = nbd_negotiate_send_meta_context(client, "qemu:allocation-depth", in nbd_negotiate_meta_queries()
1130 ret = nbd_negotiate_send_meta_context(client, context, in nbd_negotiate_meta_queries()
1139 ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); in nbd_negotiate_meta_queries()
1148 * Process all NBD_OPT_* client option commands, during fixed newstyle
1153 * 1 if client sent NBD_OPT_ABORT (i.e. on valid disconnect) or never
1157 nbd_negotiate_options(NBDClient *client, Error **errp) in nbd_negotiate_options() argument
1163 /* Client sends: in nbd_negotiate_options()
1164 [ 0 .. 3] client flags in nbd_negotiate_options()
1183 if (nbd_read32(client->ioc, &flags, "flags", NULL) < 0) { in nbd_negotiate_options()
1186 client->mode = NBD_MODE_EXPORT_NAME; in nbd_negotiate_options()
1191 client->mode = NBD_MODE_SIMPLE; in nbd_negotiate_options()
1198 error_setg(errp, "Unknown client flags 0x%" PRIx32 " received", flags); in nbd_negotiate_options()
1207 if (nbd_read64(client->ioc, &magic, "opts magic", errp) < 0) { in nbd_negotiate_options()
1216 if (nbd_read32(client->ioc, &option, "option", errp) < 0) { in nbd_negotiate_options()
1219 client->opt = option; in nbd_negotiate_options()
1221 if (nbd_read32(client->ioc, &length, "option length", errp) < 0) { in nbd_negotiate_options()
1224 assert(!client->optlen); in nbd_negotiate_options()
1225 client->optlen = length; in nbd_negotiate_options()
1235 if (client->tlscreds && in nbd_negotiate_options()
1236 client->ioc == (QIOChannel *)client->sioc) { in nbd_negotiate_options()
1245 /* Unconditionally drop the connection if the client in nbd_negotiate_options()
1247 return nbd_reject_length(client, true, errp); in nbd_negotiate_options()
1249 tioc = nbd_negotiate_handle_starttls(client, errp); in nbd_negotiate_options()
1254 object_unref(OBJECT(client->ioc)); in nbd_negotiate_options()
1255 client->ioc = tioc; in nbd_negotiate_options()
1259 /* No way to return an error to client, so drop connection */ in nbd_negotiate_options()
1265 /* Let the client keep trying, unless they asked to in nbd_negotiate_options()
1267 * client; but when replying to OPT_ABORT, be aware in nbd_negotiate_options()
1268 * that the client may hang up before receiving the in nbd_negotiate_options()
1271 ret = nbd_opt_drop(client, NBD_REP_ERR_TLS_REQD, in nbd_negotiate_options()
1284 ret = nbd_reject_length(client, false, errp); in nbd_negotiate_options()
1286 ret = nbd_negotiate_handle_list(client, errp); in nbd_negotiate_options()
1294 nbd_negotiate_send_rep(client, NBD_REP_ACK, NULL); in nbd_negotiate_options()
1298 return nbd_negotiate_handle_export_name(client, no_zeroes, in nbd_negotiate_options()
1303 ret = nbd_negotiate_handle_info(client, errp); in nbd_negotiate_options()
1312 ret = nbd_reject_length(client, false, errp); in nbd_negotiate_options()
1313 } else if (client->tlscreds) { in nbd_negotiate_options()
1314 ret = nbd_negotiate_send_rep_err(client, in nbd_negotiate_options()
1318 ret = nbd_negotiate_send_rep_err(client, in nbd_negotiate_options()
1326 ret = nbd_reject_length(client, false, errp); in nbd_negotiate_options()
1327 } else if (client->mode >= NBD_MODE_EXTENDED) { in nbd_negotiate_options()
1329 client, NBD_REP_ERR_EXT_HEADER_REQD, errp, in nbd_negotiate_options()
1331 } else if (client->mode >= NBD_MODE_STRUCTURED) { in nbd_negotiate_options()
1333 client, NBD_REP_ERR_INVALID, errp, in nbd_negotiate_options()
1336 ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); in nbd_negotiate_options()
1337 client->mode = NBD_MODE_STRUCTURED; in nbd_negotiate_options()
1343 ret = nbd_negotiate_meta_queries(client, errp); in nbd_negotiate_options()
1348 ret = nbd_reject_length(client, false, errp); in nbd_negotiate_options()
1349 } else if (client->mode >= NBD_MODE_EXTENDED) { in nbd_negotiate_options()
1351 client, NBD_REP_ERR_INVALID, errp, in nbd_negotiate_options()
1354 ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); in nbd_negotiate_options()
1355 client->mode = NBD_MODE_EXTENDED; in nbd_negotiate_options()
1360 ret = nbd_opt_drop(client, NBD_REP_ERR_UNSUP, errp, in nbd_negotiate_options()
1372 return nbd_negotiate_handle_export_name(client, no_zeroes, in nbd_negotiate_options()
1391 * 1 if client sent NBD_OPT_ABORT (i.e. on valid disconnect) or never
1394 static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp) in nbd_negotiate() argument
1407 New style negotiation header, client can send options in nbd_negotiate()
1414 qio_channel_set_blocking(client->ioc, false, NULL); in nbd_negotiate()
1415 qio_channel_set_follow_coroutine_ctx(client->ioc, true); in nbd_negotiate()
1425 * wrong with a client testing if our port is alive. in nbd_negotiate()
1427 if (nbd_write(client->ioc, buf, 18, NULL) < 0) { in nbd_negotiate()
1430 ret = nbd_negotiate_options(client, errp); in nbd_negotiate()
1438 assert(!client->optlen); in nbd_negotiate()
1453 nbd_read_eof(NBDClient *client, void *buffer, size_t size, Error **errp) in nbd_read_eof() argument
1462 len = qio_channel_readv(client->ioc, &iov, 1, errp); in nbd_read_eof()
1464 WITH_QEMU_LOCK_GUARD(&client->lock) { in nbd_read_eof()
1465 client->read_yielding = true; in nbd_read_eof()
1470 qio_channel_yield(client->ioc, G_IO_IN); in nbd_read_eof()
1471 WITH_QEMU_LOCK_GUARD(&client->lock) { in nbd_read_eof()
1472 client->read_yielding = false; in nbd_read_eof()
1473 if (client->quiescing) { in nbd_read_eof()
1497 static int coroutine_fn nbd_receive_request(NBDClient *client, NBDRequest *request, in nbd_receive_request() argument
1503 size_t size = client->mode >= NBD_MODE_EXTENDED ? in nbd_receive_request()
1506 ret = nbd_read_eof(client, buf, size, errp); in nbd_receive_request()
1536 if (client->mode >= NBD_MODE_EXTENDED) { in nbd_receive_request()
1558 void nbd_client_get(NBDClient *client) in nbd_client_get() argument
1560 qatomic_inc(&client->refcount); in nbd_client_get()
1563 void nbd_client_put(NBDClient *client) in nbd_client_put() argument
1567 if (qatomic_fetch_dec(&client->refcount) == 1) { in nbd_client_put()
1568 /* The last reference should be dropped by client->close, in nbd_client_put()
1571 assert(client->closing); in nbd_client_put()
1573 object_unref(OBJECT(client->sioc)); in nbd_client_put()
1574 object_unref(OBJECT(client->ioc)); in nbd_client_put()
1575 if (client->tlscreds) { in nbd_client_put()
1576 object_unref(OBJECT(client->tlscreds)); in nbd_client_put()
1578 g_free(client->tlsauthz); in nbd_client_put()
1579 if (client->exp) { in nbd_client_put()
1580 QTAILQ_REMOVE(&client->exp->clients, client, next); in nbd_client_put()
1581 blk_exp_unref(&client->exp->common); in nbd_client_put()
1583 g_free(client->contexts.bitmaps); in nbd_client_put()
1584 qemu_mutex_destroy(&client->lock); in nbd_client_put()
1585 g_free(client); in nbd_client_put()
1590 * Tries to release the reference to @client, but only if other references
1597 static bool nbd_client_put_nonzero(NBDClient *client) in nbd_client_put_nonzero() argument
1599 int old = qatomic_read(&client->refcount); in nbd_client_put_nonzero()
1608 old = qatomic_cmpxchg(&client->refcount, expected, expected - 1); in nbd_client_put_nonzero()
1614 static void client_close(NBDClient *client, bool negotiated) in client_close() argument
1618 WITH_QEMU_LOCK_GUARD(&client->lock) { in client_close()
1619 if (client->closing) { in client_close()
1623 client->closing = true; in client_close()
1629 qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, in client_close()
1632 /* Also tell the client, so that they release their reference. */ in client_close()
1633 if (client->close_fn) { in client_close()
1634 client->close_fn(client, negotiated); in client_close()
1638 /* Runs in export AioContext with client->lock held */
1639 static NBDRequestData *nbd_request_get(NBDClient *client) in nbd_request_get() argument
1643 assert(client->nb_requests <= MAX_NBD_REQUESTS - 1); in nbd_request_get()
1644 client->nb_requests++; in nbd_request_get()
1647 req->client = client; in nbd_request_get()
1651 /* Runs in export AioContext with client->lock held */
1654 NBDClient *client = req->client; in nbd_request_put() local
1661 client->nb_requests--; in nbd_request_put()
1663 if (client->quiescing && client->nb_requests == 0) { in nbd_request_put()
1667 nbd_client_receive_next_request(client); in nbd_request_put()
1673 NBDClient *client; in blk_aio_attached() local
1681 QTAILQ_FOREACH(client, &exp->clients, next) { in blk_aio_attached()
1682 WITH_QEMU_LOCK_GUARD(&client->lock) { in blk_aio_attached()
1683 assert(client->nb_requests == 0); in blk_aio_attached()
1684 assert(client->recv_coroutine == NULL); in blk_aio_attached()
1685 assert(client->send_coroutine == NULL); in blk_aio_attached()
1704 NBDClient *client; in nbd_drained_begin() local
1708 QTAILQ_FOREACH(client, &exp->clients, next) { in nbd_drained_begin()
1709 WITH_QEMU_LOCK_GUARD(&client->lock) { in nbd_drained_begin()
1710 client->quiescing = true; in nbd_drained_begin()
1718 NBDClient *client; in nbd_drained_end() local
1722 QTAILQ_FOREACH(client, &exp->clients, next) { in nbd_drained_end()
1723 WITH_QEMU_LOCK_GUARD(&client->lock) { in nbd_drained_end()
1724 client->quiescing = false; in nbd_drained_end()
1725 nbd_client_receive_next_request(client); in nbd_drained_end()
1733 NBDClient *client = opaque; in nbd_wake_read_bh() local
1734 qio_channel_wake_read(client->ioc); in nbd_wake_read_bh()
1740 NBDClient *client; in nbd_drained_poll() local
1744 QTAILQ_FOREACH(client, &exp->clients, next) { in nbd_drained_poll()
1745 WITH_QEMU_LOCK_GUARD(&client->lock) { in nbd_drained_poll()
1746 if (client->nb_requests != 0) { in nbd_drained_poll()
1749 * enter it here so we don't depend on the client to wake it up. in nbd_drained_poll()
1755 if (client->recv_coroutine != NULL && client->read_yielding) { in nbd_drained_poll()
1756 aio_bh_schedule_oneshot(nbd_export_aio_context(client->exp), in nbd_drained_poll()
1757 nbd_wake_read_bh, client); in nbd_drained_poll()
1981 NBDClient *client, *next; in nbd_export_request_shutdown() local
1991 QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) { in nbd_export_request_shutdown()
1992 client_close(client, true); in nbd_export_request_shutdown()
2034 static int coroutine_fn nbd_co_send_iov(NBDClient *client, struct iovec *iov, in nbd_co_send_iov() argument
2040 qemu_co_mutex_lock(&client->send_lock); in nbd_co_send_iov()
2041 client->send_coroutine = qemu_coroutine_self(); in nbd_co_send_iov()
2043 ret = qio_channel_writev_all(client->ioc, iov, niov, errp) < 0 ? -EIO : 0; in nbd_co_send_iov()
2045 client->send_coroutine = NULL; in nbd_co_send_iov()
2046 qemu_co_mutex_unlock(&client->send_lock); in nbd_co_send_iov()
2059 static int coroutine_fn nbd_co_send_simple_reply(NBDClient *client, in nbd_co_send_simple_reply() argument
2075 assert(client->mode < NBD_MODE_STRUCTURED || in nbd_co_send_simple_reply()
2076 (client->mode == NBD_MODE_STRUCTURED && in nbd_co_send_simple_reply()
2082 return nbd_co_send_iov(client, iov, 2, errp); in nbd_co_send_simple_reply()
2093 static inline void set_be_chunk(NBDClient *client, struct iovec *iov, in set_be_chunk() argument
2104 if (client->mode >= NBD_MODE_EXTENDED) { in set_be_chunk()
2126 static int coroutine_fn nbd_co_send_chunk_done(NBDClient *client, in nbd_co_send_chunk_done() argument
2136 set_be_chunk(client, iov, 1, NBD_REPLY_FLAG_DONE, in nbd_co_send_chunk_done()
2138 return nbd_co_send_iov(client, iov, 1, errp); in nbd_co_send_chunk_done()
2141 static int coroutine_fn nbd_co_send_chunk_read(NBDClient *client, in nbd_co_send_chunk_read() argument
2159 set_be_chunk(client, iov, 3, final ? NBD_REPLY_FLAG_DONE : 0, in nbd_co_send_chunk_read()
2163 return nbd_co_send_iov(client, iov, 3, errp); in nbd_co_send_chunk_read()
2166 static int coroutine_fn nbd_co_send_chunk_error(NBDClient *client, in nbd_co_send_chunk_error() argument
2184 set_be_chunk(client, iov, 3, NBD_REPLY_FLAG_DONE, in nbd_co_send_chunk_error()
2189 return nbd_co_send_iov(client, iov, 3, errp); in nbd_co_send_chunk_error()
2192 /* Do a sparse read and send the structured reply to the client.
2194 * reported to the client, at which point this function succeeds.
2196 static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client, in nbd_co_send_sparse_read() argument
2204 NBDExport *exp = client->exp; in nbd_co_send_sparse_read()
2220 ret = nbd_co_send_chunk_error(client, request, -status, msg, errp); in nbd_co_send_sparse_read()
2236 set_be_chunk(client, iov, 2, in nbd_co_send_sparse_read()
2241 ret = nbd_co_send_iov(client, iov, 2, errp); in nbd_co_send_sparse_read()
2249 ret = nbd_co_send_chunk_read(client, request, offset + progress, in nbd_co_send_sparse_read()
2335 * would result in an incorrect range reported to the client)
2436 nbd_co_send_extents(NBDClient *client, NBDRequest *request, NBDExtentArray *ea, in nbd_co_send_extents() argument
2446 if (client->mode >= NBD_MODE_EXTENDED) { in nbd_co_send_extents()
2471 set_be_chunk(client, iov, 3, last ? NBD_REPLY_FLAG_DONE : 0, type, in nbd_co_send_extents()
2474 return nbd_co_send_iov(client, iov, 3, errp); in nbd_co_send_extents()
2477 /* Get block status from the exported device and send it to the client */
2479 coroutine_fn nbd_co_send_block_status(NBDClient *client, NBDRequest *request, in nbd_co_send_block_status() argument
2488 nbd_extent_array_new(nb_extents, client->mode); in nbd_co_send_block_status()
2496 return nbd_co_send_chunk_error(client, request, -ret, in nbd_co_send_block_status()
2500 return nbd_co_send_extents(client, request, ea, last, context_id, errp); in nbd_co_send_block_status()
2536 static int coroutine_fn nbd_co_send_bitmap(NBDClient *client, in nbd_co_send_bitmap() argument
2546 nbd_extent_array_new(nb_extents, client->mode); in nbd_co_send_bitmap()
2550 return nbd_co_send_extents(client, request, ea, last, context_id, errp); in nbd_co_send_bitmap()
2555 * Called when a client wants a subset of negotiated contexts via a
2564 nbd_co_block_status_payload_read(NBDClient *client, NBDRequest *request, in nbd_co_block_status_payload_read() argument
2578 assert(client->contexts.exp == client->exp); in nbd_co_block_status_payload_read()
2579 nr_bitmaps = client->exp->nr_export_bitmaps; in nbd_co_block_status_payload_read()
2581 request->contexts->exp = client->exp; in nbd_co_block_status_payload_read()
2586 sizeof(id) * client->contexts.count)) { in nbd_co_block_status_payload_read()
2591 if (nbd_read(client->ioc, buf, payload_len, in nbd_co_block_status_payload_read()
2604 if (!client->contexts.base_allocation || in nbd_co_block_status_payload_read()
2610 if (!client->contexts.allocation_depth || in nbd_co_block_status_payload_read()
2618 if (idx >= nr_bitmaps || !client->contexts.bitmaps[idx] || in nbd_co_block_status_payload_read()
2634 return nbd_drop(client->ioc, payload_len, errp); in nbd_co_block_status_payload_read()
2638 * Collect a client request. Return 0 if request looks valid, -EIO to drop
2641 * to the client (although the caller may still need to disconnect after
2648 NBDClient *client = req->client; in nbd_co_receive_request() local
2659 ret = nbd_receive_request(client, request, errp); in nbd_co_receive_request()
2666 extended_with_payload = client->mode >= NBD_MODE_EXTENDED && in nbd_co_receive_request()
2681 if (client->mode >= NBD_MODE_STRUCTURED) { in nbd_co_receive_request()
2689 if (client->mode >= NBD_MODE_EXTENDED) { in nbd_co_receive_request()
2691 /* The client is noncompliant. Trace it, but proceed. */ in nbd_co_receive_request()
2722 ret = nbd_co_block_status_payload_read(client, request, errp); in nbd_co_receive_request()
2731 request->contexts = &client->contexts; in nbd_co_receive_request()
2763 req->data = blk_try_blockalign(client->exp->common.blk, in nbd_co_receive_request()
2774 ret = nbd_read(client->ioc, req->data, payload_len, in nbd_co_receive_request()
2777 ret = nbd_drop(client->ioc, payload_len, errp); in nbd_co_receive_request()
2788 if (client->exp->nbdflags & NBD_FLAG_READ_ONLY && check_rofs) { in nbd_co_receive_request()
2793 if (request->from > client->exp->size || in nbd_co_receive_request()
2794 request->len > client->exp->size - request->from) { in nbd_co_receive_request()
2797 client->exp->size); in nbd_co_receive_request()
2801 if (client->check_align && !QEMU_IS_ALIGNED(request->from | request->len, in nbd_co_receive_request()
2802 client->check_align)) { in nbd_co_receive_request()
2805 * it's still worth tracing client non-compliance in nbd_co_receive_request()
2810 client->check_align); in nbd_co_receive_request()
2823 * Returns 0 if connection is still live, -errno on failure to talk to client
2825 static coroutine_fn int nbd_send_generic_reply(NBDClient *client, in nbd_send_generic_reply() argument
2831 if (client->mode >= NBD_MODE_STRUCTURED && ret < 0) { in nbd_send_generic_reply()
2832 return nbd_co_send_chunk_error(client, request, -ret, error_msg, errp); in nbd_send_generic_reply()
2833 } else if (client->mode >= NBD_MODE_EXTENDED) { in nbd_send_generic_reply()
2834 return nbd_co_send_chunk_done(client, request, errp); in nbd_send_generic_reply()
2836 return nbd_co_send_simple_reply(client, request, ret < 0 ? -ret : 0, in nbd_send_generic_reply()
2843 * client as an error reply. */
2844 static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, in nbd_do_cmd_read() argument
2848 NBDExport *exp = client->exp; in nbd_do_cmd_read()
2857 return nbd_send_generic_reply(client, request, ret, in nbd_do_cmd_read()
2862 if (client->mode >= NBD_MODE_STRUCTURED && in nbd_do_cmd_read()
2865 return nbd_co_send_sparse_read(client, request, request->from, in nbd_do_cmd_read()
2871 return nbd_send_generic_reply(client, request, ret, in nbd_do_cmd_read()
2875 if (client->mode >= NBD_MODE_STRUCTURED) { in nbd_do_cmd_read()
2877 return nbd_co_send_chunk_read(client, request, request->from, data, in nbd_do_cmd_read()
2880 return nbd_co_send_chunk_done(client, request, errp); in nbd_do_cmd_read()
2883 return nbd_co_send_simple_reply(client, request, 0, in nbd_do_cmd_read()
2893 * client as an error reply.
2895 static coroutine_fn int nbd_do_cmd_cache(NBDClient *client, NBDRequest *request, in nbd_do_cmd_cache() argument
2899 NBDExport *exp = client->exp; in nbd_do_cmd_cache()
2907 return nbd_send_generic_reply(client, request, ret, in nbd_do_cmd_cache()
2913 * client as an error reply. */
2914 static coroutine_fn int nbd_handle_request(NBDClient *client, in nbd_handle_request() argument
2920 NBDExport *exp = client->exp; in nbd_handle_request()
2926 return nbd_do_cmd_cache(client, request, errp); in nbd_handle_request()
2929 return nbd_do_cmd_read(client, request, data, errp); in nbd_handle_request()
2939 return nbd_send_generic_reply(client, request, ret, in nbd_handle_request()
2955 return nbd_send_generic_reply(client, request, ret, in nbd_handle_request()
2964 return nbd_send_generic_reply(client, request, ret, in nbd_handle_request()
2972 return nbd_send_generic_reply(client, request, ret, in nbd_handle_request()
2977 assert(client->mode >= NBD_MODE_EXTENDED || in nbd_handle_request()
2984 return nbd_send_generic_reply(client, request, -EINVAL, in nbd_handle_request()
2988 ret = nbd_co_send_block_status(client, request, in nbd_handle_request()
3001 ret = nbd_co_send_block_status(client, request, in nbd_handle_request()
3013 assert(request->contexts->exp == client->exp); in nbd_handle_request()
3014 for (i = 0; i < client->exp->nr_export_bitmaps; i++) { in nbd_handle_request()
3018 ret = nbd_co_send_bitmap(client, request, in nbd_handle_request()
3019 client->exp->export_bitmaps[i], in nbd_handle_request()
3031 } else if (client->contexts.count) { in nbd_handle_request()
3032 return nbd_send_generic_reply(client, request, -EINVAL, in nbd_handle_request()
3036 return nbd_send_generic_reply(client, request, -EINVAL, in nbd_handle_request()
3044 ret = nbd_send_generic_reply(client, request, -EINVAL, msg, in nbd_handle_request()
3055 NBDClient *client = req->client; in nbd_trip() local
3068 qemu_mutex_lock(&client->lock); in nbd_trip()
3070 if (client->closing) { in nbd_trip()
3074 if (client->quiescing) { in nbd_trip()
3079 client->recv_coroutine = NULL; in nbd_trip()
3086 * set client->quiescing but by the time we get back nbd_drained_end() may in nbd_trip()
3087 * have already cleared client->quiescing. In that case we try again in nbd_trip()
3089 * client->recv_coroutine = NULL further down. in nbd_trip()
3092 assert(client->recv_coroutine == qemu_coroutine_self()); in nbd_trip()
3093 qemu_mutex_unlock(&client->lock); in nbd_trip()
3095 qemu_mutex_lock(&client->lock); in nbd_trip()
3096 } while (ret == -EAGAIN && !client->quiescing); in nbd_trip()
3098 client->recv_coroutine = NULL; in nbd_trip()
3100 if (client->closing) { in nbd_trip()
3102 * The client may be closed when we are blocked in in nbd_trip()
3112 nbd_client_receive_next_request(client); in nbd_trip()
3118 qemu_mutex_unlock(&client->lock); in nbd_trip()
3119 qio_channel_set_cork(client->ioc, true); in nbd_trip()
3123 * semantics, we should return the error to the client. */ in nbd_trip()
3127 ret = nbd_send_generic_reply(client, &request, -EINVAL, in nbd_trip()
3131 ret = nbd_handle_request(client, &request, req->data, &local_err); in nbd_trip()
3133 if (request.contexts && request.contexts != &client->contexts) { in nbd_trip()
3139 qio_channel_set_cork(client->ioc, false); in nbd_trip()
3140 qemu_mutex_lock(&client->lock); in nbd_trip()
3159 qemu_mutex_unlock(&client->lock); in nbd_trip()
3161 if (!nbd_client_put_nonzero(client)) { in nbd_trip()
3163 nbd_client_put(client); in nbd_trip()
3169 error_reportf_err(local_err, "Disconnect client, due to: "); in nbd_trip()
3173 qemu_mutex_unlock(&client->lock); in nbd_trip()
3176 client_close(client, true); in nbd_trip()
3177 nbd_client_put(client); in nbd_trip()
3182 * client->lock.
3184 static void nbd_client_receive_next_request(NBDClient *client) in nbd_client_receive_next_request() argument
3188 if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS && in nbd_client_receive_next_request()
3189 !client->quiescing) { in nbd_client_receive_next_request()
3190 nbd_client_get(client); in nbd_client_receive_next_request()
3191 req = nbd_request_get(client); in nbd_client_receive_next_request()
3192 client->recv_coroutine = qemu_coroutine_create(nbd_trip, req); in nbd_client_receive_next_request()
3193 aio_co_schedule(client->exp->common.ctx, client->recv_coroutine); in nbd_client_receive_next_request()
3207 NBDClient *client = opaque; in nbd_co_client_start() local
3211 qemu_co_mutex_init(&client->send_lock); in nbd_co_client_start()
3218 if (client->handshake_max_secs > 0) { in nbd_co_client_start()
3223 client->sioc); in nbd_co_client_start()
3226 client->handshake_max_secs * NANOSECONDS_PER_SECOND); in nbd_co_client_start()
3229 if (nbd_negotiate(client, &local_err)) { in nbd_co_client_start()
3234 client_close(client, false); in nbd_co_client_start()
3239 WITH_QEMU_LOCK_GUARD(&client->lock) { in nbd_co_client_start()
3240 nbd_client_receive_next_request(client); in nbd_co_client_start()
3245 * Create a new client listener using the given channel @sioc and @owner.
3247 * @close_fn with an indication of whether the client completed negotiation
3257 NBDClient *client; in nbd_client_new() local
3260 client = g_new0(NBDClient, 1); in nbd_client_new()
3261 qemu_mutex_init(&client->lock); in nbd_client_new()
3262 client->refcount = 1; in nbd_client_new()
3263 client->tlscreds = tlscreds; in nbd_client_new()
3265 object_ref(OBJECT(client->tlscreds)); in nbd_client_new()
3267 client->tlsauthz = g_strdup(tlsauthz); in nbd_client_new()
3268 client->handshake_max_secs = handshake_max_secs; in nbd_client_new()
3269 client->sioc = sioc; in nbd_client_new()
3271 object_ref(OBJECT(client->sioc)); in nbd_client_new()
3272 client->ioc = QIO_CHANNEL(sioc); in nbd_client_new()
3273 object_ref(OBJECT(client->ioc)); in nbd_client_new()
3274 client->close_fn = close_fn; in nbd_client_new()
3275 client->owner = owner; in nbd_client_new()
3277 co = qemu_coroutine_create(nbd_co_client_start, client); in nbd_client_new()
3282 nbd_client_owner(NBDClient *client) in nbd_client_owner() argument
3284 return client->owner; in nbd_client_owner()