aio: add non-blocking variant of aio_wait

This will be used when polling the GSource attached to an AioContext.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2012-09-24 14:37:53 +02:00
parent 4231c88d27
commit 7c0628b20e
4 changed files with 32 additions and 13 deletions

20
aio.c
View File

@ -93,13 +93,16 @@ void aio_set_event_notifier(AioContext *ctx,
(AioFlushHandler *)io_flush, notifier); (AioFlushHandler *)io_flush, notifier);
} }
bool aio_wait(AioContext *ctx) bool aio_poll(AioContext *ctx, bool blocking)
{ {
static struct timeval tv0;
AioHandler *node; AioHandler *node;
fd_set rdfds, wrfds; fd_set rdfds, wrfds;
int max_fd = -1; int max_fd = -1;
int ret; int ret;
bool busy; bool busy, progress;
progress = false;
/* /*
* If there are callbacks left that have been queued, we need to call then. * If there are callbacks left that have been queued, we need to call then.
@ -107,6 +110,11 @@ bool aio_wait(AioContext *ctx)
* does not need a complete flush (as is the case for qemu_aio_wait loops). * does not need a complete flush (as is the case for qemu_aio_wait loops).
*/ */
if (aio_bh_poll(ctx)) { if (aio_bh_poll(ctx)) {
blocking = false;
progress = true;
}
if (progress && !blocking) {
return true; return true;
} }
@ -142,11 +150,11 @@ bool aio_wait(AioContext *ctx)
/* No AIO operations? Get us out of here */ /* No AIO operations? Get us out of here */
if (!busy) { if (!busy) {
return false; return progress;
} }
/* wait until next event */ /* wait until next event */
ret = select(max_fd, &rdfds, &wrfds, NULL, NULL); ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0);
/* if we have any readable fds, dispatch event */ /* if we have any readable fds, dispatch event */
if (ret > 0) { if (ret > 0) {
@ -161,11 +169,13 @@ bool aio_wait(AioContext *ctx)
if (!node->deleted && if (!node->deleted &&
FD_ISSET(node->fd, &rdfds) && FD_ISSET(node->fd, &rdfds) &&
node->io_read) { node->io_read) {
progress = true;
node->io_read(node->opaque); node->io_read(node->opaque);
} }
if (!node->deleted && if (!node->deleted &&
FD_ISSET(node->fd, &wrfds) && FD_ISSET(node->fd, &wrfds) &&
node->io_write) { node->io_write) {
progress = true;
node->io_write(node->opaque); node->io_write(node->opaque);
} }
@ -181,5 +191,5 @@ bool aio_wait(AioContext *ctx)
} }
} }
return true; return progress;
} }

View File

@ -144,5 +144,5 @@ AioContext *aio_context_new(void)
void aio_flush(AioContext *ctx) void aio_flush(AioContext *ctx)
{ {
while (aio_wait(ctx)); while (aio_poll(ctx, true));
} }

View File

@ -534,7 +534,7 @@ void qemu_aio_flush(void)
bool qemu_aio_wait(void) bool qemu_aio_wait(void)
{ {
return aio_wait(qemu_aio_context); return aio_poll(qemu_aio_context, true);
} }
void qemu_aio_set_fd_handler(int fd, void qemu_aio_set_fd_handler(int fd,

View File

@ -133,13 +133,22 @@ void qemu_bh_delete(QEMUBH *bh);
* outstanding AIO operations have been completed or cancelled. */ * outstanding AIO operations have been completed or cancelled. */
void aio_flush(AioContext *ctx); void aio_flush(AioContext *ctx);
/* Wait for a single AIO completion to occur. This function will wait /* Progress in completing AIO work to occur. This can issue new pending
* until a single AIO event has completed and it will ensure something * aio as a result of executing I/O completion or bh callbacks.
* has moved before returning. This can issue new pending aio as
* result of executing I/O completion or bh callbacks.
* *
* Return whether there is still any pending AIO operation. */ * If there is no pending AIO operation or completion (bottom half),
bool aio_wait(AioContext *ctx); * return false. If there are pending bottom halves, return true.
*
* If there are no pending bottom halves, but there are pending AIO
* operations, it may not be possible to make any progress without
* blocking. If @blocking is true, this function will wait until one
* or more AIO events have completed, to ensure something has moved
* before returning.
*
* If @blocking is false, this function will also return false if the
* function cannot make any progress without blocking.
*/
bool aio_poll(AioContext *ctx, bool blocking);
#ifdef CONFIG_POSIX #ifdef CONFIG_POSIX
/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */