[PATCH] Random map fix
[fio.git] / engines / libaio.c
1 /*
2  * native linux aio io engine
3  *
4  */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <assert.h>
10
11 #include "../fio.h"
12 #include "../os.h"
13
14 #ifdef FIO_HAVE_LIBAIO
15
16 #define ev_to_iou(ev)   (struct io_u *) ((unsigned long) (ev)->obj)
17
18 struct libaio_data {
19         io_context_t aio_ctx;
20         struct io_event *aio_events;
21         struct io_u *sync_io_u;
22 };
23
24 static int fio_libaio_prep(struct thread_data fio_unused *td, struct io_u *io_u)
25 {
26         struct fio_file *f = io_u->file;
27
28         if (io_u->ddir == DDIR_READ)
29                 io_prep_pread(&io_u->iocb, f->fd, io_u->xfer_buf, io_u->xfer_buflen, io_u->offset);
30         else if (io_u->ddir == DDIR_WRITE)
31                 io_prep_pwrite(&io_u->iocb, f->fd, io_u->xfer_buf, io_u->xfer_buflen, io_u->offset);
32         else if (io_u->ddir == DDIR_SYNC)
33                 io_prep_fsync(&io_u->iocb, f->fd);
34         else
35                 return 1;
36
37         return 0;
38 }
39
40 static struct io_u *fio_libaio_event(struct thread_data *td, int event)
41 {
42         struct libaio_data *ld = td->io_ops->data;
43
44         if (ld->sync_io_u) {
45                 struct io_u *ret = ld->sync_io_u;
46
47                 ld->sync_io_u = NULL;
48                 return ret;
49         }
50
51         return ev_to_iou(ld->aio_events + event);
52 }
53
54 static int fio_libaio_getevents(struct thread_data *td, int min, int max,
55                                 struct timespec *t)
56 {
57         struct libaio_data *ld = td->io_ops->data;
58         long r;
59
60         if (ld->sync_io_u)
61                 return 1;
62
63         do {
64                 r = io_getevents(ld->aio_ctx, min, max, ld->aio_events, t);
65                 if (r >= min)
66                         break;
67                 else if (r == -EAGAIN) {
68                         usleep(100);
69                         continue;
70                 } else if (r == -EINTR)
71                         continue;
72                 else if (r != 0)
73                         break;
74         } while (1);
75
76         if (r < 0)
77                 r = -r;
78
79         return (int) r;
80 }
81
82 static int fio_libaio_queue(struct thread_data *td, struct io_u *io_u)
83 {
84         struct libaio_data *ld = td->io_ops->data;
85         struct iocb *iocb = &io_u->iocb;
86         long ret;
87
88         do {
89                 ret = io_submit(ld->aio_ctx, 1, &iocb);
90                 if (ret == 1)
91                         break;
92                 else if (ret == -EAGAIN || !ret)
93                         usleep(100);
94                 else if (ret == -EINTR)
95                         continue;
96                 else if (ret == -EINVAL && io_u->ddir == DDIR_SYNC) {
97                         /*
98                          * the async fsync doesn't currently seem to be
99                          * supported, so just fsync if we fail with EINVAL
100                          * for a sync. since buffered io is also sync
101                          * with libaio (still), we don't have pending
102                          * requests to flush first.
103                          */
104                         if (fsync(io_u->file->fd) < 0)
105                                 ret = errno;
106                         else {
107                                 ret = 1;
108                                 ld->sync_io_u = io_u;
109                         }
110                         break;
111                 } else
112                         break;
113         } while (1);
114
115         if (ret <= 0) {
116                 io_u->resid = io_u->xfer_buflen;
117                 io_u->error = -ret;
118                 return 1;
119         }
120
121         return 0;
122 }
123
124 static int fio_libaio_cancel(struct thread_data *td, struct io_u *io_u)
125 {
126         struct libaio_data *ld = td->io_ops->data;
127
128         return io_cancel(ld->aio_ctx, &io_u->iocb, ld->aio_events);
129 }
130
131 static void fio_libaio_cleanup(struct thread_data *td)
132 {
133         struct libaio_data *ld = td->io_ops->data;
134
135         if (ld) {
136                 io_destroy(ld->aio_ctx);
137                 if (ld->aio_events)
138                         free(ld->aio_events);
139
140                 free(ld);
141                 td->io_ops->data = NULL;
142         }
143 }
144
145 static int fio_libaio_init(struct thread_data *td)
146 {
147         struct libaio_data *ld = malloc(sizeof(*ld));
148
149         memset(ld, 0, sizeof(*ld));
150         if (io_queue_init(td->iodepth, &ld->aio_ctx)) {
151                 td_verror(td, errno);
152                 free(ld);
153                 return 1;
154         }
155
156         ld->aio_events = malloc(td->iodepth * sizeof(struct io_event));
157         memset(ld->aio_events, 0, td->iodepth * sizeof(struct io_event));
158         td->io_ops->data = ld;
159         return 0;
160 }
161
162 static struct ioengine_ops ioengine = {
163         .name           = "libaio",
164         .version        = FIO_IOOPS_VERSION,
165         .init           = fio_libaio_init,
166         .prep           = fio_libaio_prep,
167         .queue          = fio_libaio_queue,
168         .cancel         = fio_libaio_cancel,
169         .getevents      = fio_libaio_getevents,
170         .event          = fio_libaio_event,
171         .cleanup        = fio_libaio_cleanup,
172 };
173
174 #else /* FIO_HAVE_LIBAIO */
175
176 /*
177  * When we have a proper configure system in place, we simply wont build
178  * and install this io engine. For now install a crippled version that
179  * just complains and fails to load.
180  */
181 static int fio_libaio_init(struct thread_data fio_unused *td)
182 {
183         fprintf(stderr, "fio: libaio not available\n");
184         return 1;
185 }
186
187 static struct ioengine_ops ioengine = {
188         .name           = "libaio",
189         .version        = FIO_IOOPS_VERSION,
190         .init           = fio_libaio_init,
191 };
192
193 #endif
194
195 static void fio_init fio_libaio_register(void)
196 {
197         register_ioengine(&ioengine);
198 }
199
200 static void fio_exit fio_libaio_unregister(void)
201 {
202         unregister_ioengine(&ioengine);
203 }