#define HANDLE_TO_INDEX(bs, handle) ((handle) ^ ((uint64_t)(intptr_t)bs))
#define INDEX_TO_HANDLE(bs, index) ((index) ^ ((uint64_t)(intptr_t)bs))
+static void nbd_recv_coroutines_enter_all(NbdClientSession *s)
+{
+ int i;
+
+ for (i = 0; i < MAX_NBD_REQUESTS; i++) {
+ if (s->recv_coroutine[i]) {
+ qemu_coroutine_enter(s->recv_coroutine[i], NULL);
+ }
+ }
+}
+
+static void nbd_teardown_connection(NbdClientSession *client)
+{
+ /* finish any pending coroutines */
+ shutdown(client->sock, 2);
+ nbd_recv_coroutines_enter_all(client);
+
+ nbd_client_session_detach_aio_context(client);
+ closesocket(client->sock);
+ client->sock = -1;
+}
+
static void nbd_reply_ready(void *opaque)
{
NbdClientSession *s = opaque;
}
fail:
- for (i = 0; i < MAX_NBD_REQUESTS; i++) {
- if (s->recv_coroutine[i]) {
- qemu_coroutine_enter(s->recv_coroutine[i], NULL);
- }
- }
+ nbd_teardown_connection(s);
}
static void nbd_restart_write(void *opaque)
struct nbd_request *request,
QEMUIOVector *qiov, int offset)
{
+ AioContext *aio_context;
int rc, ret;
qemu_co_mutex_lock(&s->send_mutex);
s->send_coroutine = qemu_coroutine_self();
- qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, s);
+ aio_context = bdrv_get_aio_context(s->bs);
+ aio_set_fd_handler(aio_context, s->sock,
+ nbd_reply_ready, nbd_restart_write, s);
if (qiov) {
if (!s->is_unix) {
socket_set_cork(s->sock, 1);
} else {
rc = nbd_send_request(s->sock, request);
}
- qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, s);
+ aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, s);
s->send_coroutine = NULL;
qemu_co_mutex_unlock(&s->send_mutex);
return rc;
int nb_sectors, QEMUIOVector *qiov,
int offset)
{
- struct nbd_request request;
+ struct nbd_request request = { .type = NBD_CMD_READ };
struct nbd_reply reply;
ssize_t ret;
- request.type = NBD_CMD_READ;
request.from = sector_num * 512;
request.len = nb_sectors * 512;
int nb_sectors, QEMUIOVector *qiov,
int offset)
{
- struct nbd_request request;
+ struct nbd_request request = { .type = NBD_CMD_WRITE };
struct nbd_reply reply;
ssize_t ret;
- request.type = NBD_CMD_WRITE;
if (!bdrv_enable_write_cache(client->bs) &&
(client->nbdflags & NBD_FLAG_SEND_FUA)) {
request.type |= NBD_CMD_FLAG_FUA;
int nbd_client_session_co_flush(NbdClientSession *client)
{
- struct nbd_request request;
+ struct nbd_request request = { .type = NBD_CMD_FLUSH };
struct nbd_reply reply;
ssize_t ret;
return 0;
}
- request.type = NBD_CMD_FLUSH;
if (client->nbdflags & NBD_FLAG_SEND_FUA) {
request.type |= NBD_CMD_FLAG_FUA;
}
int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
int nb_sectors)
{
- struct nbd_request request;
+ struct nbd_request request = { .type = NBD_CMD_TRIM };
struct nbd_reply reply;
ssize_t ret;
if (!(client->nbdflags & NBD_FLAG_SEND_TRIM)) {
return 0;
}
- request.type = NBD_CMD_TRIM;
request.from = sector_num * 512;
request.len = nb_sectors * 512;
}
-static void nbd_teardown_connection(NbdClientSession *client)
+void nbd_client_session_detach_aio_context(NbdClientSession *client)
{
- struct nbd_request request;
-
- request.type = NBD_CMD_DISC;
- request.from = 0;
- request.len = 0;
- nbd_send_request(client->sock, &request);
+ aio_set_fd_handler(bdrv_get_aio_context(client->bs), client->sock,
+ NULL, NULL, NULL);
+}
- qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
- closesocket(client->sock);
- client->sock = -1;
+void nbd_client_session_attach_aio_context(NbdClientSession *client,
+ AioContext *new_context)
+{
+ aio_set_fd_handler(new_context, client->sock,
+ nbd_reply_ready, NULL, client);
}
void nbd_client_session_close(NbdClientSession *client)
{
+ struct nbd_request request = {
+ .type = NBD_CMD_DISC,
+ .from = 0,
+ .len = 0
+ };
+
if (!client->bs) {
return;
}
+ if (client->sock == -1) {
+ return;
+ }
+
+ nbd_send_request(client->sock, &request);
nbd_teardown_connection(client);
client->bs = NULL;
/* Now that we're connected, set the socket to be non-blocking and
* kick the reply mechanism. */
qemu_set_nonblock(sock);
- qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, client);
+ nbd_client_session_attach_aio_context(client, bdrv_get_aio_context(bs));
logout("Established connection with NBD server\n");
return 0;