Skip to content

Commit

Permalink
aio: convert aio_poll() to g_poll(3)
Browse files Browse the repository at this point in the history
AioHandler already has a GPollFD so we can directly use its
events/revents.

Add the int pollfds_idx field to AioContext so we can map g_poll(3)
results back to AioHandlers.

Reuse aio_dispatch() to invoke handlers after g_poll(3).

Signed-off-by: Stefan Hajnoczi <[email protected]>
Reviewed-by: Laszlo Ersek <[email protected]>
Message-id: [email protected]
Signed-off-by: Anthony Liguori <[email protected]>
  • Loading branch information
stefanhaRH authored and Anthony Liguori committed Feb 21, 2013
1 parent d0c8d2c commit 6b5f876
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 43 deletions.
67 changes: 24 additions & 43 deletions aio-posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct AioHandler
IOHandler *io_write;
AioFlushHandler *io_flush;
int deleted;
int pollfds_idx;
void *opaque;
QLIST_ENTRY(AioHandler) node;
};
Expand Down Expand Up @@ -85,6 +86,7 @@ void aio_set_fd_handler(AioContext *ctx,
node->io_write = io_write;
node->io_flush = io_flush;
node->opaque = opaque;
node->pollfds_idx = -1;

node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0);
node->pfd.events |= (io_write ? G_IO_OUT : 0);
Expand Down Expand Up @@ -177,10 +179,7 @@ static bool aio_dispatch(AioContext *ctx)

bool aio_poll(AioContext *ctx, bool blocking)
{
static struct timeval tv0;
AioHandler *node;
fd_set rdfds, wrfds;
int max_fd = -1;
int ret;
bool busy, progress;

Expand All @@ -206,12 +205,13 @@ bool aio_poll(AioContext *ctx, bool blocking)

ctx->walking_handlers++;

FD_ZERO(&rdfds);
FD_ZERO(&wrfds);
g_array_set_size(ctx->pollfds, 0);

/* fill fd sets */
/* fill pollfds */
busy = false;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
node->pollfds_idx = -1;

/* If there aren't pending AIO operations, don't invoke callbacks.
* Otherwise, if there are no AIO requests, qemu_aio_wait() would
* wait indefinitely.
Expand All @@ -222,13 +222,13 @@ bool aio_poll(AioContext *ctx, bool blocking)
}
busy = true;
}
if (!node->deleted && node->io_read) {
FD_SET(node->pfd.fd, &rdfds);
max_fd = MAX(max_fd, node->pfd.fd + 1);
}
if (!node->deleted && node->io_write) {
FD_SET(node->pfd.fd, &wrfds);
max_fd = MAX(max_fd, node->pfd.fd + 1);
if (!node->deleted && node->pfd.events) {
GPollFD pfd = {
.fd = node->pfd.fd,
.events = node->pfd.events,
};
node->pollfds_idx = ctx->pollfds->len;
g_array_append_val(ctx->pollfds, pfd);
}
}

Expand All @@ -240,41 +240,22 @@ bool aio_poll(AioContext *ctx, bool blocking)
}

/* wait until next event */
ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0);
ret = g_poll((GPollFD *)ctx->pollfds->data,
ctx->pollfds->len,
blocking ? -1 : 0);

/* if we have any readable fds, dispatch event */
if (ret > 0) {
/* 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;

ctx->walking_handlers++;

if (!node->deleted &&
FD_ISSET(node->pfd.fd, &rdfds) &&
node->io_read) {
node->io_read(node->opaque);
progress = true;
}
if (!node->deleted &&
FD_ISSET(node->pfd.fd, &wrfds) &&
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);
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (node->pollfds_idx != -1) {
GPollFD *pfd = &g_array_index(ctx->pollfds, GPollFD,
node->pollfds_idx);
node->pfd.revents = pfd->revents;
}
}
if (aio_dispatch(ctx)) {
progress = true;
}
}

assert(progress || busy);
Expand Down
2 changes: 2 additions & 0 deletions async.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ aio_ctx_finalize(GSource *source)

aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL);
event_notifier_cleanup(&ctx->notifier);
g_array_free(ctx->pollfds, TRUE);
}

static GSourceFuncs aio_source_funcs = {
Expand All @@ -198,6 +199,7 @@ AioContext *aio_context_new(void)
{
AioContext *ctx;
ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
event_notifier_init(&ctx->notifier, false);
aio_set_event_notifier(ctx, &ctx->notifier,
(EventNotifierHandler *)
Expand Down
3 changes: 3 additions & 0 deletions include/block/aio.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ typedef struct AioContext {

/* Used for aio_notify. */
EventNotifier notifier;

/* GPollFDs for aio_poll() */
GArray *pollfds;
} AioContext;

/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
Expand Down

0 comments on commit 6b5f876

Please sign in to comment.