This function will register the fd handler similar to aio_set_event_notifier, but the difference is the fd will only be polled in the outmost aio_poll.
This is useful in some cases like device ioeventfd, where the handler typically processes a guest request, therefore nested aio_poll shouldn't include this. Signed-off-by: Fam Zheng <f...@redhat.com> --- aio-posix.c | 33 +++++++++++++++++++++++++++------ include/block/aio.h | 23 ++++++++++++++++++++--- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/aio-posix.c b/aio-posix.c index 4abec38..05a0502 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -24,6 +24,7 @@ struct AioHandler IOHandler *io_read; IOHandler *io_write; int deleted; + bool outmost; void *opaque; QLIST_ENTRY(AioHandler) node; }; @@ -41,11 +42,12 @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd) return NULL; } -void aio_set_fd_handler(AioContext *ctx, - int fd, - IOHandler *io_read, - IOHandler *io_write, - void *opaque) +static void aio_set_fd_handler_do(AioContext *ctx, + int fd, + IOHandler *io_read, + IOHandler *io_write, + void *opaque, + bool outmost) { AioHandler *node; @@ -82,6 +84,7 @@ void aio_set_fd_handler(AioContext *ctx, node->io_read = io_read; node->io_write = io_write; node->opaque = opaque; + node->outmost = outmost; node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0); node->pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0); @@ -90,6 +93,15 @@ void aio_set_fd_handler(AioContext *ctx, aio_notify(ctx); } +void aio_set_fd_handler(AioContext *ctx, + int fd, + IOHandler *io_read, + IOHandler *io_write, + void *opaque) +{ + aio_set_fd_handler_do(ctx, fd, io_read, io_write, opaque, false); +} + void aio_set_event_notifier(AioContext *ctx, EventNotifier *notifier, EventNotifierHandler *io_read) @@ -98,6 +110,14 @@ void aio_set_event_notifier(AioContext *ctx, (IOHandler *)io_read, NULL, notifier); } +void aio_set_io_event_notifier(AioContext *ctx, + EventNotifier *notifier, + EventNotifierHandler *io_read) +{ + aio_set_fd_handler_do(ctx, event_notifier_get_fd(notifier), + (IOHandler *)io_read, NULL, notifier, true); +} + bool aio_prepare(AioContext *ctx) { return false; @@ -260,7 +280,8 @@ bool aio_poll(AioContext *ctx, bool blocking) /* fill pollfds */ QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (!node->deleted && node->pfd.events) { + if (!node->deleted && node->pfd.events + && !(was_dispatching && node->outmost)) { add_pollfd(node); } } diff --git a/include/block/aio.h b/include/block/aio.h index d2bb423..20bfb2b 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -240,9 +240,7 @@ bool aio_dispatch(AioContext *ctx); */ bool aio_poll(AioContext *ctx, bool blocking); -/* Register a file descriptor and associated callbacks. Behaves very similarly - * to qemu_set_fd_handler2. Unlike qemu_set_fd_handler2, these callbacks will - * be invoked when using aio_poll(). +/* Register a file descriptor and associated callbacks. * * Code that invokes AIO completion functions should rely on this function * instead of qemu_set_fd_handler[2]. @@ -253,6 +251,15 @@ void aio_set_fd_handler(AioContext *ctx, IOHandler *io_write, void *opaque); +/* Register a file descriptor and associated callbacks. Behaves very similarly + * to qemu_set_fd_handler: these callbacks will be invoked only by outmost + * aio_poll() directly, but not in nested polls (such as bdrv_drain() or + * bdrv_aio_cancel()). + */ +void aio_set_iohandler(AioContext *ctx, int fd, + IOHandler *io_read, + IOHandler *io_write, + void *opaque); /* Register an event notifier and associated callbacks. Behaves very similarly * to event_notifier_set_handler. Unlike event_notifier_set_handler, these callbacks * will be invoked when using aio_poll(). @@ -264,6 +271,16 @@ void aio_set_event_notifier(AioContext *ctx, EventNotifier *notifier, EventNotifierHandler *io_read); +/* Similar to aio_set_event_notifier except the notifier will only be checked + * in top level poll. + * + * Notifiers for external requests like guest I/O or monitor command should use + * this function. + */ +void aio_set_io_event_notifier(AioContext *ctx, + EventNotifier *notifier, + EventNotifierHandler *io_read); + /* Return a GSource that lets the main loop poll the file descriptors attached * to this AioContext. */ -- 2.4.1