static int nbd_co_send_request(BlockDriverState *bs, struct nbd_request *request, QEMUIOVector *qiov, int offset) { NbdClientSession *s = nbd_get_client_session(bs); AioContext *aio_context; int rc, ret, i; qemu_co_mutex_lock(&s->send_mutex); for (i = 0; i < MAX_NBD_REQUESTS; i++) { if (s->recv_coroutine[i] == NULL) { s->recv_coroutine[i] = qemu_coroutine_self(); break; } } g_assert(qemu_in_coroutine()); assert(i < MAX_NBD_REQUESTS); request->handle = INDEX_TO_HANDLE(s, i); if (!s->ioc) { qemu_co_mutex_unlock(&s->send_mutex); return -EPIPE; } s->send_coroutine = qemu_coroutine_self(); aio_context = bdrv_get_aio_context(bs); aio_set_fd_handler(aio_context, s->sioc->fd, false, nbd_reply_ready, nbd_restart_write, bs); if (qiov) { qio_channel_set_cork(s->ioc, true); rc = nbd_send_request(s->ioc, request); if (rc >= 0) { ret = nbd_wr_syncv(s->ioc, qiov->iov, qiov->niov, offset, request->len, 0); if (ret != request->len) { rc = -EIO; } } qio_channel_set_cork(s->ioc, false); } else { rc = nbd_send_request(s->ioc, request); } aio_set_fd_handler(aio_context, s->sioc->fd, false, nbd_reply_ready, NULL, bs); s->send_coroutine = NULL; qemu_co_mutex_unlock(&s->send_mutex); return rc; }
static void qio_channel_websock_set_cork(QIOChannel *ioc, bool enabled) { QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc); qio_channel_set_cork(tioc->master, enabled); }
static void qio_channel_tls_set_cork(QIOChannel *ioc, bool enabled) { QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); qio_channel_set_cork(tioc->master, enabled); }
static int nbd_co_send_request(BlockDriverState *bs, NBDRequest *request, QEMUIOVector *qiov) { NBDClientSession *s = nbd_get_client_session(bs); int rc, ret, i; qemu_co_mutex_lock(&s->send_mutex); while (s->in_flight == MAX_NBD_REQUESTS) { qemu_co_queue_wait(&s->free_sema, &s->send_mutex); } s->in_flight++; for (i = 0; i < MAX_NBD_REQUESTS; i++) { if (s->recv_coroutine[i] == NULL) { s->recv_coroutine[i] = qemu_coroutine_self(); break; } } g_assert(qemu_in_coroutine()); assert(i < MAX_NBD_REQUESTS); request->handle = INDEX_TO_HANDLE(s, i); if (!s->ioc) { qemu_co_mutex_unlock(&s->send_mutex); return -EPIPE; } if (qiov) { qio_channel_set_cork(s->ioc, true); rc = nbd_send_request(s->ioc, request); if (rc >= 0) { ret = nbd_rwv(s->ioc, qiov->iov, qiov->niov, request->len, false, NULL); if (ret != request->len) { rc = -EIO; } } qio_channel_set_cork(s->ioc, false); } else { rc = nbd_send_request(s->ioc, request); } qemu_co_mutex_unlock(&s->send_mutex); return rc; }
static int nbd_co_send_request(BlockDriverState *bs, NBDRequest *request, QEMUIOVector *qiov) { NBDClientSession *s = nbd_get_client_session(bs); int rc, i; qemu_co_mutex_lock(&s->send_mutex); while (s->in_flight == MAX_NBD_REQUESTS) { qemu_co_queue_wait(&s->free_sema, &s->send_mutex); } s->in_flight++; for (i = 0; i < MAX_NBD_REQUESTS; i++) { if (s->requests[i].coroutine == NULL) { break; } } g_assert(qemu_in_coroutine()); assert(i < MAX_NBD_REQUESTS); s->requests[i].coroutine = qemu_coroutine_self(); s->requests[i].receiving = false; request->handle = INDEX_TO_HANDLE(s, i); if (s->quit) { rc = -EIO; goto err; } if (!s->ioc) { rc = -EPIPE; goto err; } if (qiov) { qio_channel_set_cork(s->ioc, true); rc = nbd_send_request(s->ioc, request); if (rc >= 0 && !s->quit) { assert(request->len == iov_size(qiov->iov, qiov->niov)); if (qio_channel_writev_all(s->ioc, qiov->iov, qiov->niov, NULL) < 0) { rc = -EIO; } } qio_channel_set_cork(s->ioc, false); } else { rc = nbd_send_request(s->ioc, request); } err: if (rc < 0) { s->quit = true; s->requests[i].coroutine = NULL; s->in_flight--; qemu_co_queue_next(&s->free_sema); } qemu_co_mutex_unlock(&s->send_mutex); return rc; }