solarisaio.c revision 0f09e829c3e1aa24d16059ab6665098fedf17c05
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}
202