mirror of https://github.com/proxmox/mirror_qemu
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
parent
bafbd6a1c6
commit
bcdc18578d
44
aio.c
44
aio.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue