15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * QEMU aio implementation
35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright IBM, Corp. 2008
55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Authors:
75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *  Anthony Liguori   <aliguori@us.ibm.com>
85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This work is licensed under the terms of the GNU GPL, version 2.  See
105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the COPYING file in the top-level directory.
115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
15e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "block/block.h"
16031d655004e505a15e92580a16a181d1d247c4d5David 'Digit' Turner#include "qemu/queue.h"
17d0edecb426b34ddb9b10b81dea19aee04a61a385David 'Digit' Turner#include "qemu/sockets.h"
18d413fa5f2916a2a46494edb320340486b262644cDavid 'Digit' Turner#include "android/iolooper.h"
195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct AioHandler AioHandler;
215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* The list of registered AIO handlers */
23a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turnerstatic QLIST_HEAD(, AioHandler) aio_handlers;
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* This is a simple lock used to protect the aio_handlers list.  Specifically,
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * it's used to ensure that no callbacks are removed while we're walking and
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * dispatching callbacks.
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int walking_handlers;
305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct AioHandler
325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IOHandler *io_read;
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IOHandler *io_write;
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AioFlushHandler *io_flush;
377627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    AioProcessQueue *io_process_queue;
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int deleted;
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *opaque;
40a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_ENTRY(AioHandler) node;
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic AioHandler *find_aio_handler(int fd)
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AioHandler *node;
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
47a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_FOREACH(node, &aio_handlers, node) {
485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (node->fd == fd)
495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (!node->deleted)
505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return node;
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_aio_set_fd_handler(int fd,
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            IOHandler *io_read,
585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            IOHandler *io_write,
595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            AioFlushHandler *io_flush,
607627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner                            AioProcessQueue *io_process_queue,
615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            void *opaque)
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AioHandler *node;
645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    node = find_aio_handler(fd);
665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Are we deleting the fd handler? */
685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!io_read && !io_write) {
695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (node) {
705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* If the lock is held, just mark the node as deleted */
715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (walking_handlers)
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                node->deleted = 1;
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            else {
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* Otherwise, delete it for real.  We can't just mark it as
755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 * deleted because deleted nodes are only cleaned up after
765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 * releasing the walking_handlers lock.
775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 */
78a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                QLIST_REMOVE(node, node);
79aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner                g_free(node);
805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (node == NULL) {
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Alloc and insert if it's not already there */
85aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner            node = g_malloc0(sizeof(AioHandler));
865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            node->fd = fd;
87a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner            QLIST_INSERT_HEAD(&aio_handlers, node, node);
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Update handler with latest information */
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        node->io_read = io_read;
915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        node->io_write = io_write;
925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        node->io_flush = io_flush;
937627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner        node->io_process_queue = io_process_queue;
945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        node->opaque = opaque;
955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_aio_flush(void)
1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AioHandler *node;
1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    do {
1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = 0;
1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	/*
1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * If there are pending emulated aio start them now so flush
1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * will be able to return 1.
1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 */
1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_aio_wait();
1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
116a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        QLIST_FOREACH(node, &aio_handlers, node) {
1177627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner            if (node->io_flush) {
1187627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner                ret |= node->io_flush(node->opaque);
1197627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner            }
1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1217627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    } while (qemu_bh_poll() || ret > 0);
1227627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner}
1237627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner
1247627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turnerint qemu_aio_process_queue(void)
1257627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner{
1267627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    AioHandler *node;
1277627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    int ret = 0;
1287627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner
1297627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    walking_handlers = 1;
1307627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner
1317627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    QLIST_FOREACH(node, &aio_handlers, node) {
1327627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner        if (node->io_process_queue) {
1337627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner            if (node->io_process_queue(node->opaque)) {
1347627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner                ret = 1;
1357627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner            }
1367627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner        }
1377627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    }
1387627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner
1397627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    walking_handlers = 0;
1407627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner
1417627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    return ret;
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_aio_wait(void)
1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IoLooper*  looper;
1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_bh_poll())
1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1527627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    /*
1537627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner     * If there are callbacks left that have been queued, we need to call then.
1547627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner     * Return afterwards to avoid waiting needlessly in select().
1557627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner     */
1567627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner    if (qemu_aio_process_queue())
1577627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner        return;
1587627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    looper = iolooper_new();
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    do {
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        AioHandler *node;
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iolooper_reset(looper);
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        walking_handlers = 1;
1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* fill fd sets */
168a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        QLIST_FOREACH(node, &aio_handlers, node) {
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* If there aren't pending AIO operations, don't invoke callbacks.
1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner             * Otherwise, if there are no AIO requests, qemu_aio_wait() would
1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner             * wait indefinitely.
1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner             */
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (node->io_flush && node->io_flush(node->opaque) == 0)
1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (!node->deleted && node->io_read) {
1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                iolooper_add_read(looper, node->fd);
1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (!node->deleted && node->io_write) {
1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                iolooper_add_write(looper, node->fd);
1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        walking_handlers = 0;
1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
186cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije        /* No AIO operations? Get us out of here */
187cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije        if (!iolooper_has_operations(looper)) {
188cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije            break;
189cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije        }
190cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije
1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* wait until next event */
1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = iolooper_wait(looper, -1);
1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* if we have any readable fds, dispatch event */
1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret > 0) {
1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            walking_handlers = 1;
1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* we have to walk very carefully in case
1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner             * qemu_aio_set_fd_handler is called while we're walking */
200a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner            node = QLIST_FIRST(&aio_handlers);
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            while (node) {
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                AioHandler *tmp;
2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (!node->deleted &&
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    iolooper_is_read(looper, node->fd) &&
2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    node->io_read) {
2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    node->io_read(node->opaque);
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (!node->deleted &&
2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    iolooper_is_write(looper, node->fd) &&
2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    node->io_write) {
2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    node->io_write(node->opaque);
2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tmp = node;
216a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                node = QLIST_NEXT(node, node);
2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (tmp->deleted) {
219a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    QLIST_REMOVE(tmp, node);
220aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner                    g_free(tmp);
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            walking_handlers = 0;
2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } while (ret == 0);
2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iolooper_free(looper);
2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
230