aio: return "AIO in progress" state from qemu_aio_wait

The definition of when qemu_aio_flush should loop is much simpler
than it looks.  It just has to call qemu_aio_wait until it makes
no progress and all flush callbacks return false.  qemu_aio_wait
is the logical place to tell the caller about this.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
master
Paolo Bonzini 2012-04-12 14:00:55 +02:00 committed by Kevin Wolf
parent bafbd6a1c6
commit bcdc18578d
2 changed files with 22 additions and 28 deletions

44
aio.c
View File

@ -99,41 +99,26 @@ int qemu_aio_set_fd_handler(int fd,
void qemu_aio_flush(void) void qemu_aio_flush(void)
{ {
AioHandler *node; while (qemu_aio_wait());
int ret;
do {
ret = 0;
/*
* If there are pending emulated aio start them now so flush
* will be able to return 1.
*/
qemu_aio_wait();
QLIST_FOREACH(node, &aio_handlers, node) {
if (node->io_flush) {
ret |= node->io_flush(node->opaque);
}
}
} while (qemu_bh_poll() || ret > 0);
} }
void qemu_aio_wait(void) bool qemu_aio_wait(void)
{ {
int ret; int ret;
/* /*
* 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.
* Return afterwards to avoid waiting needlessly in select(). * Do not call select in this case, because it is possible that the caller
* does not need a complete flush (as is the case for qemu_aio_wait loops).
*/ */
if (qemu_bh_poll()) { if (qemu_bh_poll()) {
return; return true;
} }
do { do {
AioHandler *node; AioHandler *node;
fd_set rdfds, wrfds; fd_set rdfds, wrfds;
bool busy;
int max_fd = -1; int max_fd = -1;
walking_handlers = 1; walking_handlers = 1;
@ -142,14 +127,18 @@ void qemu_aio_wait(void)
FD_ZERO(&wrfds); FD_ZERO(&wrfds);
/* fill fd sets */ /* fill fd sets */
busy = false;
QLIST_FOREACH(node, &aio_handlers, node) { QLIST_FOREACH(node, &aio_handlers, node) {
/* If there aren't pending AIO operations, don't invoke callbacks. /* If there aren't pending AIO operations, don't invoke callbacks.
* Otherwise, if there are no AIO requests, qemu_aio_wait() would * Otherwise, if there are no AIO requests, qemu_aio_wait() would
* wait indefinitely. * wait indefinitely.
*/ */
if (node->io_flush && node->io_flush(node->opaque) == 0) if (node->io_flush) {
continue; if (node->io_flush(node->opaque) == 0) {
continue;
}
busy = true;
}
if (!node->deleted && node->io_read) { if (!node->deleted && node->io_read) {
FD_SET(node->fd, &rdfds); FD_SET(node->fd, &rdfds);
max_fd = MAX(max_fd, node->fd + 1); max_fd = MAX(max_fd, node->fd + 1);
@ -163,8 +152,9 @@ void qemu_aio_wait(void)
walking_handlers = 0; walking_handlers = 0;
/* No AIO operations? Get us out of here */ /* No AIO operations? Get us out of here */
if (max_fd == -1) if (!busy) {
break; return false;
}
/* wait until next event */ /* wait until next event */
ret = select(max_fd, &rdfds, &wrfds, NULL, NULL); ret = select(max_fd, &rdfds, &wrfds, NULL, NULL);
@ -204,4 +194,6 @@ void qemu_aio_wait(void)
walking_handlers = 0; walking_handlers = 0;
} }
} while (ret == 0); } while (ret == 0);
return true;
} }

View File

@ -48,8 +48,10 @@ void qemu_aio_flush(void);
/* Wait for a single AIO completion to occur. This function will wait /* Wait for a single AIO completion to occur. This function will wait
* until a single AIO event has completed and it will ensure something * until a single AIO event has completed and it will ensure something
* has moved before returning. This can issue new pending aio as * has moved before returning. This can issue new pending aio as
* result of executing I/O completion or bh callbacks. */ * result of executing I/O completion or bh callbacks.
void qemu_aio_wait(void); *
* Return whether there is still any pending AIO operation. */
bool qemu_aio_wait(void);
/* Register a file descriptor and associated callbacks. Behaves very similarly /* Register a file descriptor and associated callbacks. Behaves very similarly
* to qemu_set_fd_handler2. Unlike qemu_set_fd_handler2, these callbacks will * to qemu_set_fd_handler2. Unlike qemu_set_fd_handler2, these callbacks will