Because nbd_client_close removes the I/O handlers for the client socket, there is no way that any suspended coroutines are restarted. This will be a problem with the QEMU embedded NBD server, because we will have a QMP command to forcibly close all connections with the clients.
Instead, we can exploit the reference counting of NBDClients; shutdown the client socket, which will make it readable and writeable. The coroutines then will fail and exit cleanly. The last refcount finally triggers the closure of the client. Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- nbd.c | 18 +++++++++++------- nbd.h | 3 +++ 2 file modificati, 14 inserzioni(+), 7 rimozioni(-) diff --git a/nbd.c b/nbd.c index c1edbeb..cb4e8fe 100644 --- a/nbd.c +++ b/nbd.c @@ -657,18 +657,22 @@ static void nbd_client_get(NBDClient *client) static void nbd_client_put(NBDClient *client) { if (--client->refcount == 0) { + qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); + close(client->sock); + client->sock = -1; + if (client->close) { + client->close(client); + } g_free(client); } } -static void nbd_client_close(NBDClient *client) +void nbd_client_close(NBDClient *client) { - qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); - close(client->sock); - client->sock = -1; - if (client->close) { - client->close(client); - } + /* Force requests to finish. They will drop their own references, + * then we'll close the socket and free the NBDClient. + */ + shutdown(client->sock, 2); nbd_client_put(client); } diff --git a/nbd.h b/nbd.h index 40d58d3..6305d68 100644 --- a/nbd.h +++ b/nbd.h @@ -81,7 +81,10 @@ typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size, uint32_t nbdflags); void nbd_export_close(NBDExport *exp); + NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)); +void nbd_client_close(NBDClient *client); + #endif -- 1.7.11.2