]> git.proxmox.com Git - mirror_qemu.git/blobdiff - aio.c
Rename target_phys_addr_t to hwaddr
[mirror_qemu.git] / aio.c
diff --git a/aio.c b/aio.c
index 70d3cdc5aa3fd1a3b10fc0d8b9717ef734a9fcbb..c738a4e15d6487a9083cdc728fc08ff8e78d9b58 100644 (file)
--- a/aio.c
+++ b/aio.c
@@ -9,17 +9,19 @@
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
  *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
  */
 
 #include "qemu-common.h"
 #include "block.h"
-#include "sys-queue.h"
+#include "qemu-queue.h"
 #include "qemu_socket.h"
 
 typedef struct AioHandler AioHandler;
 
 /* The list of registered AIO handlers */
-static LIST_HEAD(, AioHandler) aio_handlers;
+static QLIST_HEAD(, AioHandler) aio_handlers;
 
 /* This is a simple lock used to protect the aio_handlers list.  Specifically,
  * it's used to ensure that no callbacks are removed while we're walking and
@@ -35,16 +37,17 @@ struct AioHandler
     AioFlushHandler *io_flush;
     int deleted;
     void *opaque;
-    LIST_ENTRY(AioHandler) node;
+    QLIST_ENTRY(AioHandler) node;
 };
 
 static AioHandler *find_aio_handler(int fd)
 {
     AioHandler *node;
 
-    LIST_FOREACH(node, &aio_handlers, node) {
+    QLIST_FOREACH(node, &aio_handlers, node) {
         if (node->fd == fd)
-            return node;
+            if (!node->deleted)
+                return node;
     }
 
     return NULL;
@@ -71,18 +74,16 @@ int qemu_aio_set_fd_handler(int fd,
                  * deleted because deleted nodes are only cleaned up after
                  * releasing the walking_handlers lock.
                  */
-                LIST_REMOVE(node, node);
-                qemu_free(node);
+                QLIST_REMOVE(node, node);
+                g_free(node);
             }
         }
     } else {
         if (node == NULL) {
             /* Alloc and insert if it's not already there */
-            node = qemu_mallocz(sizeof(AioHandler));
-            if (node == NULL)
-                return -ENOMEM;
+            node = g_malloc0(sizeof(AioHandler));
             node->fd = fd;
-            LIST_INSERT_HEAD(&aio_handlers, node, node);
+            QLIST_INSERT_HEAD(&aio_handlers, node, node);
         }
         /* Update handler with latest information */
         node->io_read = io_read;
@@ -97,99 +98,97 @@ int qemu_aio_set_fd_handler(int fd,
 }
 
 void qemu_aio_flush(void)
+{
+    while (qemu_aio_wait());
+}
+
+bool qemu_aio_wait(void)
 {
     AioHandler *node;
+    fd_set rdfds, wrfds;
+    int max_fd = -1;
     int ret;
+    bool busy;
+
+    /*
+     * If there are callbacks left that have been queued, we need to call then.
+     * 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()) {
+        return true;
+    }
 
-    do {
-        ret = 0;
-
-        LIST_FOREACH(node, &aio_handlers, node) {
-            ret |= node->io_flush(node->opaque);
-        }
+    walking_handlers++;
 
-        qemu_aio_wait();
-    } while (ret > 0);
-}
+    FD_ZERO(&rdfds);
+    FD_ZERO(&wrfds);
 
-void qemu_aio_wait(void)
-{
-    int ret;
+    /* fill fd sets */
+    busy = false;
+    QLIST_FOREACH(node, &aio_handlers, node) {
+        /* If there aren't pending AIO operations, don't invoke callbacks.
+         * Otherwise, if there are no AIO requests, qemu_aio_wait() would
+         * wait indefinitely.
+         */
+        if (node->io_flush) {
+            if (node->io_flush(node->opaque) == 0) {
+                continue;
+            }
+            busy = true;
+        }
+        if (!node->deleted && node->io_read) {
+            FD_SET(node->fd, &rdfds);
+            max_fd = MAX(max_fd, node->fd + 1);
+        }
+        if (!node->deleted && node->io_write) {
+            FD_SET(node->fd, &wrfds);
+            max_fd = MAX(max_fd, node->fd + 1);
+        }
+    }
 
-    if (qemu_bh_poll())
-        return;
+    walking_handlers--;
 
-    do {
-        AioHandler *node;
-        fd_set rdfds, wrfds;
-        int max_fd = -1;
+    /* No AIO operations?  Get us out of here */
+    if (!busy) {
+        return false;
+    }
 
-        walking_handlers = 1;
+    /* wait until next event */
+    ret = select(max_fd, &rdfds, &wrfds, NULL, NULL);
 
-        FD_ZERO(&rdfds);
-        FD_ZERO(&wrfds);
+    /* 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(&aio_handlers);
+        while (node) {
+            AioHandler *tmp;
 
-        /* fill fd sets */
-        LIST_FOREACH(node, &aio_handlers, node) {
-            /* If there aren't pending AIO operations, don't invoke callbacks.
-             * Otherwise, if there are no AIO requests, qemu_aio_wait() would
-             * wait indefinitely.
-             */
-            if (node->io_flush && node->io_flush(node->opaque) == 0)
-                continue;
+            walking_handlers++;
 
-            if (!node->deleted && node->io_read) {
-                FD_SET(node->fd, &rdfds);
-                max_fd = MAX(max_fd, node->fd + 1);
+            if (!node->deleted &&
+                FD_ISSET(node->fd, &rdfds) &&
+                node->io_read) {
+                node->io_read(node->opaque);
             }
-            if (!node->deleted && node->io_write) {
-                FD_SET(node->fd, &wrfds);
-                max_fd = MAX(max_fd, node->fd + 1);
+            if (!node->deleted &&
+                FD_ISSET(node->fd, &wrfds) &&
+                node->io_write) {
+                node->io_write(node->opaque);
             }
-        }
 
-        walking_handlers = 0;
-
-        /* No AIO operations?  Get us out of here */
-        if (max_fd == -1)
-            break;
-
-        /* wait until next event */
-        ret = select(max_fd, &rdfds, &wrfds, NULL, NULL);
-        if (ret == -1 && errno == EINTR)
-            continue;
-
-        /* if we have any readable fds, dispatch event */
-        if (ret > 0) {
-            walking_handlers = 1;
-
-            /* we have to walk very carefully in case
-             * qemu_aio_set_fd_handler is called while we're walking */
-            node = LIST_FIRST(&aio_handlers);
-            while (node) {
-                AioHandler *tmp;
-
-                if (!node->deleted &&
-                    FD_ISSET(node->fd, &rdfds) &&
-                    node->io_read) {
-                    node->io_read(node->opaque);
-                }
-                if (!node->deleted &&
-                    FD_ISSET(node->fd, &wrfds) &&
-                    node->io_write) {
-                    node->io_write(node->opaque);
-                }
-
-                tmp = node;
-                node = LIST_NEXT(node, node);
-
-                if (tmp->deleted) {
-                    LIST_REMOVE(tmp, node);
-                    qemu_free(tmp);
-                }
-            }
+            tmp = node;
+            node = QLIST_NEXT(node, node);
+
+            walking_handlers--;
 
-            walking_handlers = 0;
+            if (!walking_handlers && tmp->deleted) {
+                QLIST_REMOVE(tmp, node);
+                g_free(tmp);
+            }
         }
-    } while (ret == 0);
+    }
+
+    return true;
 }