13 #ifdef FIO_HAVE_POSIXAIO
15 struct posixaio_data {
16 struct io_u **aio_events;
19 static int fill_timespec(struct timespec *ts)
22 if (!clock_gettime(CLOCK_MONOTONIC, ts))
25 perror("clock_gettime");
30 static unsigned long long ts_utime_since_now(struct timespec *t)
35 if (fill_timespec(&now))
38 sec = now.tv_sec - t->tv_sec;
39 nsec = now.tv_nsec - t->tv_nsec;
40 if (sec > 0 && nsec < 0) {
50 static int fio_posixaio_cancel(struct thread_data fio_unused *td,
53 struct fio_file *f = io_u->file;
54 int r = aio_cancel(f->fd, &io_u->aiocb);
56 if (r == 1 || r == AIO_CANCELED)
62 static int fio_posixaio_prep(struct thread_data fio_unused *td,
65 struct aiocb *aiocb = &io_u->aiocb;
66 struct fio_file *f = io_u->file;
68 aiocb->aio_fildes = f->fd;
69 aiocb->aio_buf = io_u->buf;
70 aiocb->aio_nbytes = io_u->buflen;
71 aiocb->aio_offset = io_u->offset;
77 static int fio_posixaio_getevents(struct thread_data *td, int min, int max,
80 struct posixaio_data *pd = td->io_ops->data;
81 struct list_head *entry;
82 struct timespec start;
83 int r, have_timeout = 0;
85 if (t && !fill_timespec(&start))
90 list_for_each(entry, &td->io_u_busylist) {
91 struct io_u *io_u = list_entry(entry, struct io_u, list);
97 err = aio_error(&io_u->aiocb);
103 pd->aio_events[r++] = io_u;
118 unsigned long long usec;
120 usec = (t->tv_sec * 1000000) + (t->tv_nsec / 1000);
121 if (ts_utime_since_now(&start) > usec)
126 * hrmpf, we need to wait for more. we should use aio_suspend, for
127 * now just sleep a little and recheck status of busy-and-not-seen
133 static struct io_u *fio_posixaio_event(struct thread_data *td, int event)
135 struct posixaio_data *pd = td->io_ops->data;
137 return pd->aio_events[event];
140 static int fio_posixaio_queue(struct thread_data fio_unused *td,
143 struct aiocb *aiocb = &io_u->aiocb;
146 if (io_u->ddir == DDIR_READ)
147 ret = aio_read(aiocb);
148 else if (io_u->ddir == DDIR_WRITE)
149 ret = aio_write(aiocb);
151 ret = aio_fsync(O_SYNC, aiocb);
159 static void fio_posixaio_cleanup(struct thread_data *td)
161 struct posixaio_data *pd = td->io_ops->data;
164 free(pd->aio_events);
166 td->io_ops->data = NULL;
170 static int fio_posixaio_init(struct thread_data *td)
172 struct posixaio_data *pd = malloc(sizeof(*pd));
174 pd->aio_events = malloc(td->iodepth * sizeof(struct io_u *));
176 td->io_ops->data = pd;
180 struct ioengine_ops ioengine = {
182 .version = FIO_IOOPS_VERSION,
183 .init = fio_posixaio_init,
184 .prep = fio_posixaio_prep,
185 .queue = fio_posixaio_queue,
186 .cancel = fio_posixaio_cancel,
187 .getevents = fio_posixaio_getevents,
188 .event = fio_posixaio_event,
189 .cleanup = fio_posixaio_cleanup,
192 #else /* FIO_HAVE_POSIXAIO */
195 * When we have a proper configure system in place, we simply wont build
196 * and install this io engine. For now install a crippled version that
197 * just complains and fails to load.
199 static int fio_posixaio_init(struct thread_data fio_unused *td)
201 fprintf(stderr, "fio: posixaio not available\n");
205 struct ioengine_ops ioengine = {
207 .version = FIO_IOOPS_VERSION,
208 .init = fio_posixaio_init,