[PATCH] Warn on writable strings
[fio.git] / engines / fio-engine-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 #include "fio.h"
11 #include "os.h"
12
13 #ifdef FIO_HAVE_LIBAIO
14
15 #define ev_to_iou(ev)   (struct io_u *) ((unsigned long) (ev)->obj)
16
17 struct libaio_data {
18         io_context_t aio_ctx;
19         struct io_event *aio_events;
20 };
21
22 static int fio_libaio_prep(struct thread_data fio_unused *td, struct io_u *io_u)
23 {
24         struct fio_file *f = io_u->file;
25
26         if (io_u->ddir == DDIR_READ)
27                 io_prep_pread(&io_u->iocb, f->fd, io_u->buf, io_u->buflen, io_u->offset);
28         else if (io_u->ddir == DDIR_WRITE)
29                 io_prep_pwrite(&io_u->iocb, f->fd, io_u->buf, io_u->buflen, io_u->offset);
30         else if (io_u->ddir == DDIR_SYNC)
31                 io_prep_fsync(&io_u->iocb, f->fd);
32         else
33                 return 1;
34
35         return 0;
36 }
37
38 static struct io_u *fio_libaio_event(struct thread_data *td, int event)
39 {
40         struct libaio_data *ld = td->io_ops->data;
41
42         return ev_to_iou(ld->aio_events + event);
43 }
44
45 static int fio_libaio_getevents(struct thread_data *td, int min, int max,
46                                 struct timespec *t)
47 {
48         struct libaio_data *ld = td->io_ops->data;
49         long r;
50
51         do {
52                 r = io_getevents(ld->aio_ctx, min, max, ld->aio_events, t);
53                 if (r == -EAGAIN) {
54                         usleep(100);
55                         continue;
56                 } else if (r == -EINTR)
57                         continue;
58                 else if (r != 0)
59                         break;
60         } while (1);
61
62         if (r < 0)
63                 r = -r;
64
65         return (int) r;
66 }
67
68 static int fio_libaio_queue(struct thread_data *td, struct io_u *io_u)
69 {
70         struct libaio_data *ld = td->io_ops->data;
71         struct iocb *iocb = &io_u->iocb;
72         long ret;
73
74         do {
75                 ret = io_submit(ld->aio_ctx, 1, &iocb);
76                 if (ret == 1)
77                         return 0;
78                 else if (ret == -EAGAIN || !ret)
79                         usleep(100);
80                 else if (ret == -EINTR)
81                         continue;
82                 else
83                         break;
84         } while (1);
85
86         if (ret <= 0) {
87                 io_u->resid = io_u->buflen;
88                 io_u->error = -ret;
89                 return 1;
90         }
91
92         return 0;
93 }
94
95 static int fio_libaio_cancel(struct thread_data *td, struct io_u *io_u)
96 {
97         struct libaio_data *ld = td->io_ops->data;
98
99         return io_cancel(ld->aio_ctx, &io_u->iocb, ld->aio_events);
100 }
101
102 static void fio_libaio_cleanup(struct thread_data *td)
103 {
104         struct libaio_data *ld = td->io_ops->data;
105
106         if (ld) {
107                 io_destroy(ld->aio_ctx);
108                 if (ld->aio_events)
109                         free(ld->aio_events);
110
111                 free(ld);
112                 td->io_ops->data = NULL;
113         }
114 }
115
116 static int fio_libaio_init(struct thread_data *td)
117 {
118         struct libaio_data *ld = malloc(sizeof(*ld));
119
120         memset(ld, 0, sizeof(*ld));
121         if (io_queue_init(td->iodepth, &ld->aio_ctx)) {
122                 td_verror(td, errno);
123                 return 1;
124         }
125
126         ld->aio_events = malloc(td->iodepth * sizeof(struct io_event));
127         memset(ld->aio_events, 0, td->iodepth * sizeof(struct io_event));
128         td->io_ops->data = ld;
129         return 0;
130 }
131
132 struct ioengine_ops ioengine = {
133         .name           = "libaio",
134         .version        = FIO_IOOPS_VERSION,
135         .init           = fio_libaio_init,
136         .prep           = fio_libaio_prep,
137         .queue          = fio_libaio_queue,
138         .cancel         = fio_libaio_cancel,
139         .getevents      = fio_libaio_getevents,
140         .event          = fio_libaio_event,
141         .cleanup        = fio_libaio_cleanup,
142 };
143
144 #else /* FIO_HAVE_LIBAIO */
145
146 /*
147  * When we have a proper configure system in place, we simply wont build
148  * and install this io engine. For now install a crippled version that
149  * just complains and fails to load.
150  */
151 static int fio_libaio_init(struct thread_data fio_unused *td)
152 {
153         fprintf(stderr, "fio: libaio not available\n");
154         return 1;
155 }
156
157 struct ioengine_ops ioengine = {
158         .name           = "libaio",
159         .version        = FIO_IOOPS_VERSION,
160         .init           = fio_libaio_init,
161 };
162
163 #endif