1cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
2cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * QEMU posix-aio emulation
3cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
4cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Copyright IBM, Corp. 2008
5cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
6cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Authors:
7cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *  Anthony Liguori   <aliguori@us.ibm.com>
8cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
9cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * This work is licensed under the terms of the GNU GPL, version 2.  See
10cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * the COPYING file in the top-level directory.
11cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
12cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
13cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
14cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <sys/ioctl.h>
15cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <sys/types.h>
16cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <pthread.h>
17cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <unistd.h>
18cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <errno.h>
19cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <time.h>
20cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <signal.h>
21cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <string.h>
22cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <stdlib.h>
23cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <stdio.h>
24cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
25cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include "qemu-queue.h"
26cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include "osdep.h"
271646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner#include "sysemu.h"
28cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include "qemu-common.h"
29cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include "block_int.h"
30cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
31cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include "block/raw-posix-aio.h"
32cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
33cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
34cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstruct qemu_paiocb {
35cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCB common;
36cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int aio_fildes;
37cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    union {
38cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        struct iovec *aio_iov;
39cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        void *aio_ioctl_buf;
40cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    };
41cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int aio_niov;
42cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    size_t aio_nbytes;
43cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#define aio_ioctl_cmd   aio_nbytes /* for QEMU_AIO_IOCTL */
44cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ev_signo;
45cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    off_t aio_offset;
46cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
47cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_ENTRY(qemu_paiocb) node;
48cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int aio_type;
49cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ssize_t ret;
50cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int active;
51cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct qemu_paiocb *next;
52cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
53cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int async_context_id;
54cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner};
55cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
56cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnertypedef struct PosixAioState {
57cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int rfd, wfd;
58cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct qemu_paiocb *first_aio;
59cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner} PosixAioState;
60cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
61cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
62cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
63cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
64cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic pthread_t thread_id;
65cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic pthread_attr_t attr;
66cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int max_threads = 64;
67cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int cur_threads = 0;
68cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int idle_threads = 0;
69cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QTAILQ_HEAD(, qemu_paiocb) request_list;
70cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
71cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifdef CONFIG_PREADV
72cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int preadv_present = 1;
73cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#else
74cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int preadv_present = 0;
75cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
76cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
77cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void die2(int err, const char *what)
78cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
79cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    fprintf(stderr, "%s failed: %s\n", what, strerror(err));
80cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    abort();
81cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
82cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
83cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void die(const char *what)
84cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
85cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    die2(errno, what);
86cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
87cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
88cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void mutex_lock(pthread_mutex_t *mutex)
89cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
90cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret = pthread_mutex_lock(mutex);
91cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret) die2(ret, "pthread_mutex_lock");
92cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
93cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
94cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void mutex_unlock(pthread_mutex_t *mutex)
95cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
96cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret = pthread_mutex_unlock(mutex);
97cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret) die2(ret, "pthread_mutex_unlock");
98cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
99cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
100cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
101cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                           struct timespec *ts)
102cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
103cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret = pthread_cond_timedwait(cond, mutex, ts);
104cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret && ret != ETIMEDOUT) die2(ret, "pthread_cond_timedwait");
105cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
106cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
107cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
108cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void cond_signal(pthread_cond_t *cond)
109cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
110cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret = pthread_cond_signal(cond);
111cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret) die2(ret, "pthread_cond_signal");
112cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
113cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
114cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void thread_create(pthread_t *thread, pthread_attr_t *attr,
115cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                          void *(*start_routine)(void*), void *arg)
116cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
117cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret = pthread_create(thread, attr, start_routine, arg);
118cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret) die2(ret, "pthread_create");
119cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
120cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
121cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb)
122cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
123cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
124cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
125cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
126cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret == -1)
127cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -errno;
128cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
129cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
130cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * This looks weird, but the aio code only consideres a request
1311646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner     * successful if it has written the number full number of bytes.
132cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     *
133cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command,
134cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * so in fact we return the ioctl command here to make posix_aio_read()
135cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * happy..
136cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
137cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return aiocb->aio_nbytes;
138cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
139cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
140cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t handle_aiocb_flush(struct qemu_paiocb *aiocb)
141cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
142cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
143cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
144cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = qemu_fdatasync(aiocb->aio_fildes);
145cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret == -1)
146cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -errno;
147cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
148cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
149cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
150cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifdef CONFIG_PREADV
151cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
152cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t
153cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerqemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
154cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
155cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return preadv(fd, iov, nr_iov, offset);
156cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
157cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
158cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t
159cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerqemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
160cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
161cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return pwritev(fd, iov, nr_iov, offset);
162cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
163cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
164cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#else
165cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
166cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t
167cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerqemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
168cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
169cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOSYS;
170cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
171cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
172cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t
173cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerqemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
174cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
175cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOSYS;
176cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
177cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
178cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
179cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
180cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
181cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
182cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    size_t offset = 0;
183cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ssize_t len;
184cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
185cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    do {
186cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (aiocb->aio_type & QEMU_AIO_WRITE)
187cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            len = qemu_pwritev(aiocb->aio_fildes,
188cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                               aiocb->aio_iov,
189cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                               aiocb->aio_niov,
190cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                               aiocb->aio_offset + offset);
191cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         else
192cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            len = qemu_preadv(aiocb->aio_fildes,
193cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              aiocb->aio_iov,
194cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              aiocb->aio_niov,
195cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              aiocb->aio_offset + offset);
196cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } while (len == -1 && errno == EINTR);
197cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
198cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (len == -1)
199cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -errno;
200cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return len;
201cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
202cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
203cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf)
204cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
205cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ssize_t offset = 0;
206cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ssize_t len;
207cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
208cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while (offset < aiocb->aio_nbytes) {
209cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         if (aiocb->aio_type & QEMU_AIO_WRITE)
210cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner             len = pwrite(aiocb->aio_fildes,
211cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                          (const char *)buf + offset,
212cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                          aiocb->aio_nbytes - offset,
213cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                          aiocb->aio_offset + offset);
214cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         else
215cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner             len = pread(aiocb->aio_fildes,
216cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                         buf + offset,
217cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                         aiocb->aio_nbytes - offset,
218cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                         aiocb->aio_offset + offset);
219cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
220cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         if (len == -1 && errno == EINTR)
221cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner             continue;
222cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         else if (len == -1) {
223cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner             offset = -errno;
224cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner             break;
225cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         } else if (len == 0)
226cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner             break;
227cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
228cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         offset += len;
229cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
230cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
231cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return offset;
232cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
233cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
234cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb)
235cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
236cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ssize_t nbytes;
237cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    char *buf;
238cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
239cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) {
240cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /*
241cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         * If there is just a single buffer, and it is properly aligned
242cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         * we can just use plain pread/pwrite without any problems.
243cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         */
244cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (aiocb->aio_niov == 1)
245cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner             return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
246cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
247cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /*
248cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         * We have more than one iovec, and all are properly aligned.
249cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         *
250cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         * Try preadv/pwritev first and fall back to linearizing the
251cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         * buffer if it's not supported.
252cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         */
253cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (preadv_present) {
254cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            nbytes = handle_aiocb_rw_vector(aiocb);
255cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (nbytes == aiocb->aio_nbytes)
256cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                return nbytes;
257cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (nbytes < 0 && nbytes != -ENOSYS)
258cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                return nbytes;
259cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            preadv_present = 0;
260cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
261cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
262cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /*
263cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         * XXX(hch): short read/write.  no easy way to handle the reminder
264cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         * using these interfaces.  For now retry using plain
265cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         * pread/pwrite?
266cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         */
267cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
268cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
269cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
270cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Ok, we have to do it the hard way, copy all segments into
271cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * a single aligned buffer.
272cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
2731646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner    buf = qemu_blockalign(aiocb->common.bs, aiocb->aio_nbytes);
274cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (aiocb->aio_type & QEMU_AIO_WRITE) {
275cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char *p = buf;
276cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int i;
277cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
278cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        for (i = 0; i < aiocb->aio_niov; ++i) {
279cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
280cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            p += aiocb->aio_iov[i].iov_len;
281cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
282cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
283cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
284cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    nbytes = handle_aiocb_rw_linear(aiocb, buf);
285cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!(aiocb->aio_type & QEMU_AIO_WRITE)) {
286cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char *p = buf;
287cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        size_t count = aiocb->aio_nbytes, copy;
288cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int i;
289cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
290cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        for (i = 0; i < aiocb->aio_niov && count; ++i) {
291cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            copy = count;
292cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (copy > aiocb->aio_iov[i].iov_len)
293cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                copy = aiocb->aio_iov[i].iov_len;
294cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            memcpy(aiocb->aio_iov[i].iov_base, p, copy);
295cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            p     += copy;
296cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            count -= copy;
297cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
298cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
299cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_vfree(buf);
300cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
301cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return nbytes;
302cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
303cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
304cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void *aio_thread(void *unused)
305cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
306cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    pid_t pid;
307cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
308cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    pid = getpid();
309cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
310cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while (1) {
311cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        struct qemu_paiocb *aiocb;
312cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ssize_t ret = 0;
313cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qemu_timeval tv;
314cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        struct timespec ts;
315cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
316cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qemu_gettimeofday(&tv);
317cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ts.tv_sec = tv.tv_sec + 10;
318cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ts.tv_nsec = 0;
319cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
320cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mutex_lock(&lock);
321cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
322cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        while (QTAILQ_EMPTY(&request_list) &&
323cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner               !(ret == ETIMEDOUT)) {
324cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = cond_timedwait(&cond, &lock, &ts);
325cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
326cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
327cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (QTAILQ_EMPTY(&request_list))
328cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            break;
329cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
330cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        aiocb = QTAILQ_FIRST(&request_list);
331cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QTAILQ_REMOVE(&request_list, aiocb, node);
332cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        aiocb->active = 1;
333cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        idle_threads--;
334cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mutex_unlock(&lock);
335cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
336cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
337cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        case QEMU_AIO_READ:
338cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        case QEMU_AIO_WRITE:
339cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = handle_aiocb_rw(aiocb);
340cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            break;
341cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        case QEMU_AIO_FLUSH:
342cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = handle_aiocb_flush(aiocb);
343cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            break;
344cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        case QEMU_AIO_IOCTL:
345cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = handle_aiocb_ioctl(aiocb);
346cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            break;
347cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        default:
348cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
349cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = -EINVAL;
350cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            break;
351cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
352cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
353cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mutex_lock(&lock);
354cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        aiocb->ret = ret;
355cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        idle_threads++;
356cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mutex_unlock(&lock);
357cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
358cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (kill(pid, aiocb->ev_signo)) die("kill failed");
359cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
360cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
361cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    idle_threads--;
362cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    cur_threads--;
363cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mutex_unlock(&lock);
364cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
365cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return NULL;
366cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
367cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
368cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void spawn_thread(void)
369cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
370cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    sigset_t set, oldset;
371cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
372cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    cur_threads++;
373cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    idle_threads++;
374cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
375cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* block all signals */
376cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (sigfillset(&set)) die("sigfillset");
377cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (sigprocmask(SIG_SETMASK, &set, &oldset)) die("sigprocmask");
378cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
379cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    thread_create(&thread_id, &attr, aio_thread, NULL);
380cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
381cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (sigprocmask(SIG_SETMASK, &oldset, NULL)) die("sigprocmask restore");
382cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
383cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
384cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void qemu_paio_submit(struct qemu_paiocb *aiocb)
385cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
386cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    aiocb->ret = -EINPROGRESS;
387cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    aiocb->active = 0;
388cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mutex_lock(&lock);
389cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (idle_threads == 0 && cur_threads < max_threads)
390cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        spawn_thread();
391cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_INSERT_TAIL(&request_list, aiocb, node);
392cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mutex_unlock(&lock);
393cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    cond_signal(&cond);
394cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
395cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
396cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic ssize_t qemu_paio_return(struct qemu_paiocb *aiocb)
397cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
398cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ssize_t ret;
399cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
400cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mutex_lock(&lock);
401cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = aiocb->ret;
402cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mutex_unlock(&lock);
403cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
404cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
405cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
406cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
407cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int qemu_paio_error(struct qemu_paiocb *aiocb)
408cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
409cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ssize_t ret = qemu_paio_return(aiocb);
410cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
411cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0)
412cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = -ret;
413cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    else
414cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = 0;
415cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
416cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
417cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
418cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
419cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int posix_aio_process_queue(void *opaque)
420cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
421cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    PosixAioState *s = opaque;
422cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct qemu_paiocb *acb, **pacb;
423cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
424cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int result = 0;
425cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int async_context_id = get_async_context_id();
426cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
427cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for(;;) {
428cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        pacb = &s->first_aio;
429cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        for(;;) {
430cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            acb = *pacb;
431cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (!acb)
432cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                return result;
433cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
434cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* we're only interested in requests in the right context */
435cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (acb->async_context_id != async_context_id) {
436cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                pacb = &acb->next;
437cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                continue;
438cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
439cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
440cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = qemu_paio_error(acb);
441cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (ret == ECANCELED) {
442cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                /* remove the request */
443cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                *pacb = acb->next;
444cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                qemu_aio_release(acb);
445cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                result = 1;
446cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            } else if (ret != EINPROGRESS) {
447cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                /* end of aio */
448cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                if (ret == 0) {
449cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                    ret = qemu_paio_return(acb);
450cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                    if (ret == acb->aio_nbytes)
451cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        ret = 0;
452cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                    else
453cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        ret = -EINVAL;
454cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                } else {
455cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                    ret = -ret;
456cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                }
4571646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner
4581646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner                //trace_paio_complete(acb, acb->common.opaque, ret);
4591646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner
460cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                /* remove the request */
461cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                *pacb = acb->next;
462cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                /* call the callback */
463cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                acb->common.cb(acb->common.opaque, ret);
464cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                qemu_aio_release(acb);
465cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                result = 1;
466cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                break;
467cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            } else {
468cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                pacb = &acb->next;
469cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
470cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
471cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
472cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
473cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return result;
474cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
475cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
476cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void posix_aio_read(void *opaque)
477cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
478cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    PosixAioState *s = opaque;
479cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ssize_t len;
480cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
481cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* read all bytes from signal pipe */
482cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (;;) {
483cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char bytes[16];
484cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
485cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        len = read(s->rfd, bytes, sizeof(bytes));
486cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (len == -1 && errno == EINTR)
487cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            continue; /* try again */
488cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (len == sizeof(bytes))
489cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            continue; /* more to read */
490cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        break;
491cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
492cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
493cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    posix_aio_process_queue(s);
494cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
495cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
496cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int posix_aio_flush(void *opaque)
497cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
498cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    PosixAioState *s = opaque;
499cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return !!s->first_aio;
500cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
501cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
502cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic PosixAioState *posix_aio_state;
503cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
504cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void aio_signal_handler(int signum)
505cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
506cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (posix_aio_state) {
507cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char byte = 0;
508cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ssize_t ret;
509cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
510cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = write(posix_aio_state->wfd, &byte, sizeof(byte));
511cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (ret < 0 && errno != EAGAIN)
512cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            die("write()");
513cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
514cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
515cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_service_io();
516cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
517cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
518cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void paio_remove(struct qemu_paiocb *acb)
519cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
520cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct qemu_paiocb **pacb;
521cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
522cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* remove the callback from the queue */
523cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    pacb = &posix_aio_state->first_aio;
524cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for(;;) {
525cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (*pacb == NULL) {
526cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            fprintf(stderr, "paio_remove: aio request not found!\n");
527cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            break;
528cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        } else if (*pacb == acb) {
529cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            *pacb = acb->next;
530cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_aio_release(acb);
531cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            break;
532cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
533cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        pacb = &(*pacb)->next;
534cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
535cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
536cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
537cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void paio_cancel(BlockDriverAIOCB *blockacb)
538cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
539cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb;
540cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int active = 0;
541cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
5421646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner    //trace_paio_cancel(acb, acb->common.opaque);
5431646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner
544cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mutex_lock(&lock);
545cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!acb->active) {
546cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QTAILQ_REMOVE(&request_list, acb, node);
547cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb->ret = -ECANCELED;
548cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else if (acb->ret == -EINPROGRESS) {
549cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        active = 1;
550cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
551cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mutex_unlock(&lock);
552cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
553cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (active) {
554cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* fail safe: if the aio could not be canceled, we wait for
555cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner           it */
556cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        while (qemu_paio_error(acb) == EINPROGRESS)
557cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ;
558cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
559cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
560cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    paio_remove(acb);
561cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
562cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
563cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic AIOPool raw_aio_pool = {
564cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    .aiocb_size         = sizeof(struct qemu_paiocb),
565cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    .cancel             = paio_cancel,
566cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner};
567cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
568cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
569cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
570cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque, int type)
571cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
572cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct qemu_paiocb *acb;
573cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
574cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
575cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!acb)
576cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return NULL;
577cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_type = type;
578cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_fildes = fd;
579cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->ev_signo = SIGUSR2;
580cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->async_context_id = get_async_context_id();
581cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
582cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (qiov) {
583cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb->aio_iov = qiov->iov;
584cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb->aio_niov = qiov->niov;
585cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
586cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_nbytes = nb_sectors * 512;
587cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_offset = sector_num * 512;
588cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
589cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->next = posix_aio_state->first_aio;
590cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    posix_aio_state->first_aio = acb;
591cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
5921646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner    //trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
593cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_paio_submit(acb);
594cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return &acb->common;
595cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
596cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
597cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
598cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        unsigned long int req, void *buf,
599cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
600cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
601cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct qemu_paiocb *acb;
602cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
603cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
604cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!acb)
605cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return NULL;
606cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_type = QEMU_AIO_IOCTL;
607cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_fildes = fd;
608cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->ev_signo = SIGUSR2;
6091646b4eb23bb788e9398583c442db9b70a85921aDavid 'Digit' Turner    acb->async_context_id = get_async_context_id();
610cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_offset = 0;
611cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_ioctl_buf = buf;
612cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->aio_ioctl_cmd = req;
613cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
614cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->next = posix_aio_state->first_aio;
615cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    posix_aio_state->first_aio = acb;
616cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
617cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_paio_submit(acb);
618cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return &acb->common;
619cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
620cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
621cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint paio_init(void)
622cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
623cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct sigaction act;
624cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    PosixAioState *s;
625cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int fds[2];
626cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
627cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
628cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (posix_aio_state)
629cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
630cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
631cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    s = qemu_malloc(sizeof(PosixAioState));
632cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
633cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    sigfillset(&act.sa_mask);
634cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
635cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    act.sa_handler = aio_signal_handler;
636cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    sigaction(SIGUSR2, &act, NULL);
637cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
638cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    s->first_aio = NULL;
639cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (qemu_pipe(fds) == -1) {
640cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        fprintf(stderr, "failed to create pipe\n");
641cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -1;
642cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
643cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
644cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    s->rfd = fds[0];
645cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    s->wfd = fds[1];
646cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
647cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    fcntl(s->rfd, F_SETFL, O_NONBLOCK);
648cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    fcntl(s->wfd, F_SETFL, O_NONBLOCK);
649cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
650cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush,
651cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        posix_aio_process_queue, s);
652cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
653cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = pthread_attr_init(&attr);
654cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret)
655cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        die2(ret, "pthread_attr_init");
656cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
657cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
658cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret)
659cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        die2(ret, "pthread_attr_setdetachstate");
660cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
661cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_INIT(&request_list);
662cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
663cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    posix_aio_state = s;
664cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
665cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
666