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