@@ -602,6 +602,37 @@ struct NBDExport {
QSIMPLEQ_HEAD(, NBDRequest) requests;
};
+struct NBDClient {
+ int refcount;
+ void (*close)(NBDClient *client);
+
+ NBDExport *exp;
+ int sock;
+};
+
+static void nbd_client_get(NBDClient *client)
+{
+ client->refcount++;
+}
+
+static void nbd_client_put(NBDClient *client)
+{
+ if (--client->refcount == 0) {
+ g_free(client);
+ }
+}
+
+static 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);
+ }
+ nbd_client_put(client);
+}
+
static NBDRequest *nbd_request_get(NBDExport *exp)
{
NBDRequest *req;
@@ -714,9 +745,11 @@ out:
return rc;
}
-int nbd_trip(NBDExport *exp, int csock)
+static int nbd_trip(NBDClient *client)
{
+ NBDExport *exp = client->exp;
NBDRequest *req = nbd_request_get(exp);
+ int csock = client->sock;
struct nbd_request request;
struct nbd_reply reply;
int rc = -1;
@@ -837,3 +870,31 @@ out:
nbd_request_put(exp, req);
return rc;
}
+
+static void nbd_read(void *opaque)
+{
+ NBDClient *client = opaque;
+
+ nbd_client_get(client);
+ if (nbd_trip(client) != 0) {
+ nbd_client_close(client);
+ }
+
+ nbd_client_put(client);
+}
+
+NBDClient *nbd_client_new(NBDExport *exp, int csock,
+ void (*close)(NBDClient *))
+{
+ NBDClient *client;
+ if (nbd_negotiate(csock, exp->size, exp->nbdflags) == -1) {
+ return NULL;
+ }
+ client = g_malloc0(sizeof(NBDClient));
+ client->refcount = 1;
+ client->exp = exp;
+ client->sock = csock;
+ client->close = close;
+ qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client);
+ return client;
+}
@@ -77,10 +77,12 @@ int nbd_client(int fd);
int nbd_disconnect(int fd);
typedef struct NBDExport NBDExport;
+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);
-int nbd_trip(NBDExport *exp, int csock);
+NBDClient *nbd_client_new(NBDExport *exp, int csock,
+ void (*close)(NBDClient *));
#endif
@@ -186,15 +186,9 @@ static int nbd_can_accept(void *opaque)
return nb_fds < shared;
}
-static void nbd_read(void *opaque)
+static void nbd_client_closed(NBDClient *client)
{
- int fd = (uintptr_t) opaque;
-
- if (nbd_trip(&exp, fd) != 0) {
- qemu_set_fd_handler2(fd, NULL, NULL, NULL, NULL);
- close(fd);
- nb_fds--;
- }
+ nb_fds--;
}
static void nbd_accept(void *opaque)
@@ -204,8 +198,7 @@ static void nbd_accept(void *opaque)
socklen_t addr_len = sizeof(addr);
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
- if (fd != -1 && nbd_negotiate(fd, exp.size, exp.nbdflags) != -1) {
- qemu_set_fd_handler2(fd, NULL, nbd_read, NULL, (void *) (intptr_t) fd);
+ if (fd != -1 && nbd_client_new(exp, fd, nbd_client_closed)) {
nb_fds++;
}
}
This patch sets up the fd handler in nbd.c instead of qemu-nbd.c. It introduces NBDClient, which wraps the arguments to nbd_trip in a single structure, so that we can add a notifier to it. This way, qemu-nbd can know about disconnections. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- nbd.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- nbd.h | 4 ++- qemu-nbd.c | 13 ++--------- 3 files changed, 68 insertions(+), 12 deletions(-)