Add Solaris native aio engine
[fio.git] / engines / solarisaio.c
CommitLineData
417f0068
JA
1/*
2 * Native Solaris async IO engine
3 *
4 */
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8#include <errno.h>
9
10#include "../fio.h"
11
12#ifdef FIO_HAVE_SOLARISAIO
13
14#include <sys/asynch.h>
15
16struct solarisaio_data {
17 struct io_u **aio_events;
18 unsigned int nr;
19};
20
21static int fio_solarisaio_cancel(struct thread_data fio_unused *td,
22 struct io_u *io_u)
23{
24 return aiocancel(&io_u->resultp);
25}
26
27static int fio_solarisaio_prep(struct thread_data fio_unused *td,
28 struct io_u *io_u)
29{
30 io_u->resultp.aio_return = AIO_INPROGRESS;
31 return 0;
32}
33
34static int fio_solarisaio_getevents(struct thread_data *td, unsigned int min,
35 unsigned int max, struct timespec *t)
36{
37 struct solarisaio_data *sd = td->io_ops->data;
38 struct timeval tv;
39 unsigned int r;
40
41 r = 0;
42 do {
43 struct io_u *io_u;
44 aio_result_t *p;
45
46 if (!min || !t) {
47 tv.tv_sec = 0;
48 tv.tv_usec = 0;
49 } else {
50 tv.tv_sec = t->tv_sec;
51 tv.tv_usec = t->tv_nsec / 1000;
52 }
53
54 p = aiowait(&tv);
55 if (p) {
56 io_u = container_of(p, struct io_u, resultp);
57
58 sd->aio_events[r++] = io_u;
59 sd->nr--;
60
61 if (io_u->resultp.aio_return >= 0) {
62 io_u->resid = io_u->xfer_buflen
63 - io_u->resultp.aio_return;
64 io_u->error = 0;
65 } else
66 io_u->error = io_u->resultp.aio_return;
67 }
68 } while (r < min);
69
70 return r;
71}
72
73static struct io_u *fio_solarisaio_event(struct thread_data *td, int event)
74{
75 struct solarisaio_data *sd = td->io_ops->data;
76
77 return sd->aio_events[event];
78}
79
80static int fio_solarisaio_queue(struct thread_data fio_unused *td,
81 struct io_u *io_u)
82{
83 struct solarisaio_data *sd = td->io_ops->data;
84 struct fio_file *f = io_u->file;
85 off_t off;
86 int ret;
87
88 fio_ro_check(td, io_u);
89
90 if (io_u->ddir == DDIR_SYNC) {
91 if (sd->nr)
92 return FIO_Q_BUSY;
93 if (fsync(f->fd) < 0)
94 io_u->error = errno;
95
96 return FIO_Q_COMPLETED;
97 }
98
99 if (sd->nr == td->o.iodepth)
100 return FIO_Q_BUSY;
101
102 off = io_u->offset;
103 if (io_u->ddir == DDIR_READ)
104 ret = aioread(f->fd, io_u->xfer_buf, io_u->xfer_buflen, off,
105 SEEK_SET, &io_u->resultp);
106 else
107 ret = aiowrite(f->fd, io_u->xfer_buf, io_u->xfer_buflen, off,
108 SEEK_SET, &io_u->resultp);
109 if (ret) {
110 io_u->error = errno;
111 td_verror(td, io_u->error, "xfer");
112 return FIO_Q_COMPLETED;
113 }
114
115 sd->nr++;
116 return FIO_Q_QUEUED;
117}
118
119static void fio_solarisaio_cleanup(struct thread_data *td)
120{
121 struct solarisaio_data *sd = td->io_ops->data;
122
123 if (sd) {
124 free(sd->aio_events);
125 free(sd);
126 }
127}
128
129static int fio_solarisaio_init(struct thread_data *td)
130{
131 struct solarisaio_data *sd = malloc(sizeof(*sd));
132
133 memset(sd, 0, sizeof(*sd));
134 sd->aio_events = malloc(td->o.iodepth * sizeof(struct io_u *));
135 memset(sd->aio_events, 0, td->o.iodepth * sizeof(struct io_u *));
136
137 td->io_ops->data = sd;
138 return 0;
139}
140
141static struct ioengine_ops ioengine = {
142 .name = "solarisaio",
143 .version = FIO_IOOPS_VERSION,
144 .init = fio_solarisaio_init,
145 .prep = fio_solarisaio_prep,
146 .queue = fio_solarisaio_queue,
147 .cancel = fio_solarisaio_cancel,
148 .getevents = fio_solarisaio_getevents,
149 .event = fio_solarisaio_event,
150 .cleanup = fio_solarisaio_cleanup,
151 .open_file = generic_open_file,
152 .close_file = generic_close_file,
153};
154
155#else /* FIO_HAVE_SOLARISAIO */
156
157/*
158 * When we have a proper configure system in place, we simply wont build
159 * and install this io engine. For now install a crippled version that
160 * just complains and fails to load.
161 */
162static int fio_solarisaio_init(struct thread_data fio_unused *td)
163{
164 fprintf(stderr, "fio: solarisaio not available\n");
165 return 1;
166}
167
168static struct ioengine_ops ioengine = {
169 .name = "solarisaio",
170 .version = FIO_IOOPS_VERSION,
171 .init = fio_solarisaio_init,
172};
173
174#endif
175
176static void fio_init fio_solarisaio_register(void)
177{
178 register_ioengine(&ioengine);
179}
180
181static void fio_exit fio_solarisaio_unregister(void)
182{
183 unregister_ioengine(&ioengine);
184}