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);
}
bool aio_wait(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;
bool busy, progress;
progress = false;
/*
* 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).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
progress = true;
}
if (progress && !blocking) {
return true;
}
@ -142,11 +150,11 @@ bool aio_wait(AioContext *ctx)
/* No AIO operations? Get us out of here */
if (!busy) {
return false;
return progress;
}
/* 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 (ret > 0) {
@ -161,11 +169,13 @@ bool aio_wait(AioContext *ctx)
if (!node->deleted &&
FD_ISSET(node->fd, &rdfds) &&
node->io_read) {
progress = true;
node->io_read(node->opaque);
}
if (!node->deleted &&
FD_ISSET(node->fd, &wrfds) &&
node->io_write) {
progress = true;
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)
{
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)
{
return aio_wait(qemu_aio_context);
return aio_poll(qemu_aio_context, true);
}
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. */
void aio_flush(AioContext *ctx);
/* Wait for a single AIO completion to occur. This function will wait
* until a single AIO event has completed and it will ensure something
* has moved before returning. This can issue new pending aio as
* result of executing I/O completion or bh callbacks.
/* Progress in completing AIO work to occur. This can issue new pending
* aio as a result of executing I/O completion or bh callbacks.
*
* Return whether there is still any pending AIO operation. */
bool aio_wait(AioContext *ctx);
* If there is no pending AIO operation or completion (bottom half),
* 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
/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */