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