Do not communicate after the first error to avoid communicating throught broken channel. The only exclusion is try to send NBD_CMD_DISC anyway on in nbd_client_close.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- block/nbd-client.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 7c151b3dd3..6109abf8a7 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -49,6 +49,8 @@ static void nbd_teardown_connection(BlockDriverState *bs) { NBDClientSession *client = nbd_get_client_session(bs); + client->eio_to_all = true; + if (!client->ioc) { /* Already closed */ return; } @@ -75,11 +77,15 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque) NBDReply reply; for (;;) { + if (s->eio_to_all) { + break; + } + ret = nbd_receive_reply(s->ioc, &reply, &local_err); if (ret < 0) { error_report_err(local_err); } - if (ret <= 0) { + if (ret <= 0 || s->eio_to_all) { break; } @@ -99,7 +105,7 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque) ret = nbd_rwv(s->ioc, s->requests[i].qiov->iov, s->requests[i].qiov->niov, s->requests[i].request->len, true, NULL); - if (ret != s->requests[i].request->len) { + if (ret != s->requests[i].request->len || s->eio_to_all) { break; } } @@ -133,6 +139,10 @@ static int nbd_co_request(BlockDriverState *bs, NBDClientSession *s = nbd_get_client_session(bs); int rc, ret, i; + if (s->eio_to_all) { + return -EIO; + } + qemu_co_mutex_lock(&s->send_mutex); while (s->in_flight == MAX_NBD_REQUESTS) { qemu_co_queue_wait(&s->free_sema, &s->send_mutex); @@ -152,16 +162,16 @@ static int nbd_co_request(BlockDriverState *bs, s->requests[i].request = request; s->requests[i].qiov = qiov; - if (!s->ioc) { + if (s->eio_to_all) { qemu_co_mutex_unlock(&s->send_mutex); - return -EPIPE; + return -EIO; } if (request->type == NBD_CMD_WRITE) { assert(qiov != NULL); qio_channel_set_cork(s->ioc, true); rc = nbd_send_request(s->ioc, request); - if (rc >= 0) { + if (rc == 0 && !s->eio_to_all) { ret = nbd_rwv(s->ioc, qiov->iov, qiov->niov, request->len, false, NULL); if (ret != request->len) { @@ -174,13 +184,16 @@ static int nbd_co_request(BlockDriverState *bs, } qemu_co_mutex_unlock(&s->send_mutex); + if (s->eio_to_all) { + rc = -EIO; + } if (rc < 0) { goto out; } /* Wait until we're woken up by nbd_read_reply_entry. */ qemu_coroutine_yield(); - if (!s->ioc || s->eio_to_all) { + if (s->eio_to_all) { rc = -EIO; goto out; } @@ -335,6 +348,7 @@ int nbd_client_init(BlockDriverState *bs, logout("session init %s\n", export); qio_channel_set_blocking(QIO_CHANNEL(sioc), true, NULL); + client->eio_to_all = false; client->info.request_sizes = true; ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), export, tlscreds, hostname, -- 2.11.1