From: Anthony Liguori <anthony@codemonkey.ws>
To: Paolo Bonzini <pbonzini@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 09/17] aio: prepare for introducing GSource-based dispatch
Date: Tue, 25 Sep 2012 17:01:19 -0500 [thread overview]
Message-ID: <87r4ppn4nk.fsf@codemonkey.ws> (raw)
In-Reply-To: <1348577763-12920-10-git-send-email-pbonzini@redhat.com>
Paolo Bonzini <pbonzini@redhat.com> writes:
> This adds a GPollFD to each AioHandler. It will then be possible to
> attach these GPollFDs to a GSource, and from there to the main loop.
> aio_wait examines the GPollFDs and avoids calling select() if any
> is set (similar to what it does if bottom halves are available).
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> aio.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------
> qemu-aio.h | 7 ++++++
> 2 file modificati, 78 inserzioni(+), 11 rimozioni(-)
>
> diff --git a/aio.c b/aio.c
> index 95ad467..c848a9f 100644
> --- a/aio.c
> +++ b/aio.c
> @@ -20,7 +20,7 @@
>
> struct AioHandler
> {
> - int fd;
> + GPollFD pfd;
> IOHandler *io_read;
> IOHandler *io_write;
> AioFlushHandler *io_flush;
> @@ -34,7 +34,7 @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd)
> AioHandler *node;
>
> QLIST_FOREACH(node, &ctx->aio_handlers, node) {
> - if (node->fd == fd)
> + if (node->pfd.fd == fd)
> if (!node->deleted)
> return node;
> }
> @@ -57,9 +57,10 @@ void aio_set_fd_handler(AioContext *ctx,
> if (!io_read && !io_write) {
> if (node) {
> /* If the lock is held, just mark the node as deleted */
> - if (ctx->walking_handlers)
> + if (ctx->walking_handlers) {
> node->deleted = 1;
> - else {
> + node->pfd.revents = 0;
> + } else {
> /* Otherwise, delete it for real. We can't just mark it as
> * deleted because deleted nodes are only cleaned up after
> * releasing the walking_handlers lock.
> @@ -72,7 +73,7 @@ void aio_set_fd_handler(AioContext *ctx,
> if (node == NULL) {
> /* Alloc and insert if it's not already there */
> node = g_malloc0(sizeof(AioHandler));
> - node->fd = fd;
> + node->pfd.fd = fd;
> QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
> }
> /* Update handler with latest information */
> @@ -80,6 +81,10 @@ void aio_set_fd_handler(AioContext *ctx,
> node->io_write = io_write;
> node->io_flush = io_flush;
> node->opaque = opaque;
> +
> + node->pfd.events = G_IO_ERR;
> + node->pfd.events |= (io_read ? G_IO_IN | G_IO_HUP : 0);
> + node->pfd.events |= (io_write ? G_IO_OUT : 0);
> }
Should we even set G_IO_ERR? I think that corresponds to exceptfd in
select() but we've never set that historically. I know glib recommends
it but I don't think it's applicable to how we use it.
Moreover, the way you do dispatch, if G_IO_ERR did occur, we'd dispatch
both the read and write handlers which definitely isn't right.
I think it's easiest just to drop it.
> }
>
> @@ -93,6 +98,25 @@ void aio_set_event_notifier(AioContext *ctx,
> (AioFlushHandler *)io_flush, notifier);
> }
>
> +bool aio_pending(AioContext *ctx)
> +{
> + AioHandler *node;
> +
> + QLIST_FOREACH(node, &ctx->aio_handlers, node) {
> + int revents;
> +
> + revents = node->pfd.revents & node->pfd.events;
> + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
> + return true;
> + }
> + if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> bool aio_poll(AioContext *ctx, bool blocking)
> {
> static struct timeval tv0;
> @@ -114,6 +138,42 @@ bool aio_poll(AioContext *ctx, bool blocking)
> progress = true;
> }
>
> + /*
> + * Then dispatch any pending callbacks from the GSource.
> + *
> + * We have to walk very carefully in case qemu_aio_set_fd_handler is
> + * called while we're walking.
> + */
> + node = QLIST_FIRST(&ctx->aio_handlers);
> + while (node) {
> + AioHandler *tmp;
> + int revents;
> +
> + ctx->walking_handlers++;
> +
> + revents = node->pfd.revents & node->pfd.events;
> + node->pfd.revents &= ~revents;
This is interesting and I must admit I don't understand why it's
necessary. What case are you trying to handle?
> +
> + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
> + node->io_read(node->opaque);
> + progress = true;
> + }
> + if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
> + node->io_write(node->opaque);
> + progress = true;
> + }
> +
> + tmp = node;
> + node = QLIST_NEXT(node, node);
> +
> + ctx->walking_handlers--;
> +
> + if (!ctx->walking_handlers && tmp->deleted) {
> + QLIST_REMOVE(tmp, node);
> + g_free(tmp);
> + }
> + }
> +
> if (progress && !blocking) {
> return true;
> }
> @@ -137,12 +197,12 @@ bool aio_poll(AioContext *ctx, bool blocking)
> busy = true;
> }
> if (!node->deleted && node->io_read) {
> - FD_SET(node->fd, &rdfds);
> - max_fd = MAX(max_fd, node->fd + 1);
> + FD_SET(node->pfd.fd, &rdfds);
> + max_fd = MAX(max_fd, node->pfd.fd + 1);
> }
> if (!node->deleted && node->io_write) {
> - FD_SET(node->fd, &wrfds);
> - max_fd = MAX(max_fd, node->fd + 1);
> + FD_SET(node->pfd.fd, &wrfds);
> + max_fd = MAX(max_fd, node->pfd.fd + 1);
> }
> }
>
> @@ -167,12 +227,12 @@ bool aio_poll(AioContext *ctx, bool blocking)
> ctx->walking_handlers++;
>
> if (!node->deleted &&
> - FD_ISSET(node->fd, &rdfds) &&
> + FD_ISSET(node->pfd.fd, &rdfds) &&
> node->io_read) {
> node->io_read(node->opaque);
> }
> if (!node->deleted &&
> - FD_ISSET(node->fd, &wrfds) &&
> + FD_ISSET(node->pfd.fd, &wrfds) &&
> node->io_write) {
> node->io_write(node->opaque);
> }
> diff --git a/qemu-aio.h b/qemu-aio.h
> index f19201e..ac24896 100644
> --- a/qemu-aio.h
> +++ b/qemu-aio.h
> @@ -133,6 +133,13 @@ void qemu_bh_delete(QEMUBH *bh);
> * outstanding AIO operations have been completed or cancelled. */
> void aio_flush(AioContext *ctx);
>
> +/* Return whether there are any pending callbacks from the GSource
> + * attached to the AioContext.
> + *
> + * This is used internally in the implementation of the GSource.
> + */
> +bool aio_pending(AioContext *ctx);
> +
> /* Progress in completing AIO work to occur. This can issue new pending
> * aio as a result of executing I/O completion or bh callbacks.
> *
> --
> 1.7.12
Regards,
Anthony Liguori
next prev parent reply other threads:[~2012-09-25 22:01 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-09-25 12:55 [Qemu-devel] [RFC PATCH 00/17] Support for multiple "AIO contexts" Paolo Bonzini
2012-09-25 12:55 ` [Qemu-devel] [PATCH 01/17] build: do not rely on indirect inclusion of qemu-config.h Paolo Bonzini
2012-09-25 12:55 ` [Qemu-devel] [PATCH 02/17] event_notifier: enable it to use pipes Paolo Bonzini
2012-10-08 7:03 ` Stefan Hajnoczi
2012-09-25 12:55 ` [Qemu-devel] [PATCH 03/17] event_notifier: add Win32 implementation Paolo Bonzini
2012-09-25 12:55 ` [Qemu-devel] [PATCH 04/17] aio: change qemu_aio_set_fd_handler to return void Paolo Bonzini
2012-09-25 21:47 ` Anthony Liguori
2012-09-25 12:55 ` [Qemu-devel] [PATCH 05/17] aio: provide platform-independent API Paolo Bonzini
2012-09-25 21:48 ` Anthony Liguori
2012-09-25 12:55 ` [Qemu-devel] [PATCH 06/17] aio: introduce AioContext, move bottom halves there Paolo Bonzini
2012-09-25 21:51 ` Anthony Liguori
2012-09-26 6:30 ` Paolo Bonzini
2012-09-25 12:55 ` [Qemu-devel] [PATCH 07/17] aio: add I/O handlers to the AioContext interface Paolo Bonzini
2012-09-25 12:55 ` [Qemu-devel] [PATCH 08/17] aio: add non-blocking variant of aio_wait Paolo Bonzini
2012-09-25 21:56 ` Anthony Liguori
2012-09-25 12:55 ` [Qemu-devel] [PATCH 09/17] aio: prepare for introducing GSource-based dispatch Paolo Bonzini
2012-09-25 22:01 ` Anthony Liguori [this message]
2012-09-26 6:36 ` Paolo Bonzini
2012-09-26 6:48 ` Paolo Bonzini
2012-09-29 11:28 ` Blue Swirl
2012-10-01 6:40 ` Paolo Bonzini
2012-09-25 12:55 ` [Qemu-devel] [PATCH 10/17] aio: add Win32 implementation Paolo Bonzini
2012-09-25 12:55 ` [Qemu-devel] [PATCH 11/17] aio: make AioContexts GSources Paolo Bonzini
2012-09-25 22:06 ` Anthony Liguori
2012-09-26 6:40 ` Paolo Bonzini
2012-09-25 12:55 ` [Qemu-devel] [PATCH 12/17] aio: add aio_notify Paolo Bonzini
2012-09-25 22:07 ` Anthony Liguori
2012-09-25 12:55 ` [Qemu-devel] [PATCH 13/17] aio: call aio_notify after setting I/O handlers Paolo Bonzini
2012-09-25 22:07 ` Anthony Liguori
2012-09-25 12:56 ` [Qemu-devel] [PATCH 14/17] main-loop: use GSource to poll AIO file descriptors Paolo Bonzini
2012-09-25 22:09 ` Anthony Liguori
2012-09-26 6:38 ` Paolo Bonzini
2012-09-25 12:56 ` [Qemu-devel] [PATCH 15/17] main-loop: use aio_notify for qemu_notify_event Paolo Bonzini
2012-09-25 22:10 ` Anthony Liguori
2012-09-25 12:56 ` [Qemu-devel] [PATCH 16/17] aio: clean up now-unused functions Paolo Bonzini
2012-09-25 22:11 ` Anthony Liguori
2012-09-25 12:56 ` [Qemu-devel] [PATCH 17/17] linux-aio: use event notifiers Paolo Bonzini
2012-09-26 12:28 ` [Qemu-devel] [RFC PATCH 00/17] Support for multiple "AIO contexts" Kevin Wolf
2012-09-26 13:32 ` Paolo Bonzini
2012-09-26 14:31 ` Kevin Wolf
2012-09-26 15:48 ` Paolo Bonzini
2012-09-27 7:11 ` Kevin Wolf
2012-09-27 7:43 ` Paolo Bonzini
2012-10-08 11:39 ` Stefan Hajnoczi
2012-10-08 13:00 ` Paolo Bonzini
2012-10-09 9:08 ` [Qemu-devel] Block I/O outside the QEMU global mutex was "Re: [RFC PATCH 00/17] Support for multiple "AIO contexts"" Stefan Hajnoczi
2012-10-09 9:26 ` Avi Kivity
2012-10-09 10:36 ` Paolo Bonzini
2012-10-09 10:52 ` Avi Kivity
2012-10-09 11:08 ` Paolo Bonzini
2012-10-09 11:55 ` Avi Kivity
2012-10-09 12:01 ` Paolo Bonzini
2012-10-09 12:18 ` Jan Kiszka
2012-10-09 12:28 ` Avi Kivity
2012-10-09 12:22 ` Avi Kivity
2012-10-09 13:11 ` Paolo Bonzini
2012-10-09 13:21 ` Avi Kivity
2012-10-09 13:50 ` Paolo Bonzini
2012-10-09 14:24 ` Avi Kivity
2012-10-09 14:35 ` Paolo Bonzini
2012-10-09 14:41 ` Avi Kivity
2012-10-09 14:05 ` Stefan Hajnoczi
2012-10-09 15:02 ` Anthony Liguori
2012-10-09 15:06 ` Paolo Bonzini
2012-10-09 15:37 ` Anthony Liguori
2012-10-09 16:26 ` Paolo Bonzini
2012-10-09 18:26 ` Anthony Liguori
2012-10-10 7:11 ` Paolo Bonzini
2012-10-10 12:25 ` Anthony Liguori
2012-10-10 13:31 ` Paolo Bonzini
2012-10-10 14:44 ` Anthony Liguori
2012-10-11 12:28 ` Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87r4ppn4nk.fsf@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.