13 struct posixaio_data {
14 struct io_u **aio_events;
17 static int fill_timespec(struct timespec *ts)
20 if (!clock_gettime(CLOCK_MONOTONIC, ts))
23 perror("clock_gettime");
28 static unsigned long long ts_utime_since_now(struct timespec *t)
33 if (fill_timespec(&now))
36 sec = now.tv_sec - t->tv_sec;
37 nsec = now.tv_nsec - t->tv_nsec;
38 if (sec > 0 && nsec < 0) {
48 static int fio_posixaio_sync(struct thread_data fio_unused *td,
54 static int fio_posixaio_cancel(struct thread_data fio_unused *td,
57 struct fio_file *f = io_u->file;
58 int r = aio_cancel(f->fd, &io_u->aiocb);
60 if (r == 1 || r == AIO_CANCELED)
66 static int fio_posixaio_prep(struct thread_data fio_unused *td,
69 struct aiocb *aiocb = &io_u->aiocb;
70 struct fio_file *f = io_u->file;
72 aiocb->aio_fildes = f->fd;
73 aiocb->aio_buf = io_u->buf;
74 aiocb->aio_nbytes = io_u->buflen;
75 aiocb->aio_offset = io_u->offset;
81 static int fio_posixaio_getevents(struct thread_data *td, int min, int max,
84 struct posixaio_data *pd = td->io_ops->data;
85 struct list_head *entry;
86 struct timespec start;
87 int r, have_timeout = 0;
89 if (t && !fill_timespec(&start))
94 list_for_each(entry, &td->io_u_busylist) {
95 struct io_u *io_u = list_entry(entry, struct io_u, list);
101 err = aio_error(&io_u->aiocb);
107 pd->aio_events[r++] = io_u;
122 unsigned long long usec;
124 usec = (t->tv_sec * 1000000) + (t->tv_nsec / 1000);
125 if (ts_utime_since_now(&start) > usec)
130 * hrmpf, we need to wait for more. we should use aio_suspend, for
131 * now just sleep a little and recheck status of busy-and-not-seen
137 static struct io_u *fio_posixaio_event(struct thread_data *td, int event)
139 struct posixaio_data *pd = td->io_ops->data;
141 return pd->aio_events[event];
144 static int fio_posixaio_queue(struct thread_data fio_unused *td,
147 struct aiocb *aiocb = &io_u->aiocb;
150 if (io_u->ddir == DDIR_READ)
151 ret = aio_read(aiocb);
153 ret = aio_write(aiocb);
161 static void fio_posixaio_cleanup(struct thread_data *td)
163 struct posixaio_data *pd = td->io_ops->data;
166 free(pd->aio_events);
168 td->io_ops->data = NULL;
172 static int fio_posixaio_init(struct thread_data *td)
174 struct posixaio_data *pd = malloc(sizeof(*pd));
176 pd->aio_events = malloc(td->iodepth * sizeof(struct io_u *));
178 td->io_ops->data = pd;
182 struct ioengine_ops ioengine = {
184 .version = FIO_IOOPS_VERSION,
185 .init = fio_posixaio_init,
186 .prep = fio_posixaio_prep,
187 .queue = fio_posixaio_queue,
188 .cancel = fio_posixaio_cancel,
189 .getevents = fio_posixaio_getevents,
190 .event = fio_posixaio_event,
191 .cleanup = fio_posixaio_cleanup,
192 .sync = fio_posixaio_sync,