+ if (active) {
+ /* fail safe: if the aio could not be canceled, we wait for
+ it */
+ while (qemu_paio_error(acb) == EINPROGRESS)
+ ;
+ }
+
+ paio_remove(acb);
+}
+
+static AIOPool raw_aio_pool = {
+ .aiocb_size = sizeof(struct qemu_paiocb),
+ .cancel = paio_cancel,
+};
+
+BlockDriverAIOCB *paio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque, int type)
+{
+ struct qemu_paiocb *acb;
+
+ acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
+ if (!acb)
+ return NULL;
+ acb->aio_type = type;
+ acb->aio_fildes = fd;
+ acb->ev_signo = SIGUSR2;
+ if (qiov) {
+ acb->aio_iov = qiov->iov;
+ acb->aio_niov = qiov->niov;
+ }
+ acb->aio_nbytes = nb_sectors * 512;
+ acb->aio_offset = sector_num * 512;
+
+ acb->next = posix_aio_state->first_aio;
+ posix_aio_state->first_aio = acb;
+
+ qemu_paio_submit(acb);
+ return &acb->common;
+}
+
+BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
+ unsigned long int req, void *buf,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ struct qemu_paiocb *acb;
+
+ acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
+ if (!acb)
+ return NULL;
+ acb->aio_type = QEMU_AIO_IOCTL;
+ acb->aio_fildes = fd;
+ acb->ev_signo = SIGUSR2;
+ acb->aio_offset = 0;
+ acb->aio_ioctl_buf = buf;
+ acb->aio_ioctl_cmd = req;
+
+ acb->next = posix_aio_state->first_aio;
+ posix_aio_state->first_aio = acb;
+
+ qemu_paio_submit(acb);
+ return &acb->common;
+}
+
+void *paio_init(void)
+{
+ struct sigaction act;
+ PosixAioState *s;
+ int fds[2];
+ int ret;
+
+ if (posix_aio_state)
+ return posix_aio_state;
+
+ s = qemu_malloc(sizeof(PosixAioState));
+
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
+ act.sa_handler = aio_signal_handler;
+ sigaction(SIGUSR2, &act, NULL);
+
+ s->first_aio = NULL;
+ if (pipe(fds) == -1) {
+ fprintf(stderr, "failed to create pipe\n");
+ return NULL;
+ }
+
+ s->rfd = fds[0];
+ s->wfd = fds[1];
+
+ fcntl(s->rfd, F_SETFL, O_NONBLOCK);
+ fcntl(s->wfd, F_SETFL, O_NONBLOCK);
+
+ qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s);
+
+ ret = pthread_attr_init(&attr);
+ if (ret)
+ die2(ret, "pthread_attr_init");
+
+ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if (ret)
+ die2(ret, "pthread_attr_setdetachstate");
+
+ QTAILQ_INIT(&request_list);
+
+ posix_aio_state = s;
+
+ return posix_aio_state;