Keep the NBD server always in the same AIO context as the exported BDS by calling bdrv_follow_aio() and implementing the required callbacks.
Signed-off-by: Max Reitz <mre...@redhat.com> --- nbd.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/nbd.c b/nbd.c index 803b3d7..1898c5e 100644 --- a/nbd.c +++ b/nbd.c @@ -808,6 +808,36 @@ static void nbd_request_put(NBDRequest *req) nbd_client_put(client); } +static int nbd_can_read(void *opaque); +static void nbd_read(void *opaque); +static void nbd_restart_write(void *opaque); + +static void bs_aio_attach(AioContext *ctx, void *opaque) +{ + NBDExport *exp = opaque; + NBDClient *client; + + QTAILQ_FOREACH(client, &exp->clients, next) { + aio_set_fd_handler2(ctx, client->sock, + nbd_can_read, nbd_read, NULL, client); + } + + exp->ctx = ctx; +} + +static void bs_aio_detach(void *opaque) +{ + NBDExport *exp = opaque; + NBDClient *client; + + QTAILQ_FOREACH(client, &exp->clients, next) { + aio_set_fd_handler2(exp->ctx, client->sock, + NULL, NULL, NULL, NULL); + } + + exp->ctx = NULL; +} + NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size, uint32_t nbdflags, void (*close)(NBDExport *)) @@ -822,6 +852,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, exp->close = close; exp->ctx = bdrv_get_aio_context(bs); bdrv_ref(bs); + bdrv_follow_aio(bs, bs_aio_attach, bs_aio_detach, exp); return exp; } @@ -869,6 +900,7 @@ void nbd_export_close(NBDExport *exp) nbd_export_set_name(exp, NULL); nbd_export_put(exp); if (exp->bs) { + bdrv_unfollow_aio(exp->bs, bs_aio_attach, bs_aio_detach, exp); bdrv_unref(exp->bs); exp->bs = NULL; } @@ -912,10 +944,6 @@ void nbd_export_close_all(void) } } -static int nbd_can_read(void *opaque); -static void nbd_read(void *opaque); -static void nbd_restart_write(void *opaque); - static ssize_t nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply, int len) { -- 1.9.3