configure: kill windows FIO_HAVE_FDATASYNC
[fio.git] / engines / guasi.c
CommitLineData
609342ff
DL
1/*
2 * guasi engine
3 *
4 * IO engine using the GUASI library.
5 *
46eaa157
DL
6 * This is currently disabled. To enable it, execute:
7 *
8 * $ export EXTFLAGS="-DFIO_HAVE_GUASI"
9 * $ export EXTLIBS="-lguasi"
10 *
11 * before running make. You'll need the GUASI lib as well:
609342ff
DL
12 *
13 * http://www.xmailserver.org/guasi-lib.html
14 *
15 */
16#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19#include <errno.h>
20#include <assert.h>
21
22#include "../fio.h"
609342ff 23
609342ff 24#define GFIO_MIN_THREADS 32
d6c6810f 25#ifndef GFIO_MAX_THREADS
97c26cbe 26#define GFIO_MAX_THREADS 2000
d6c6810f 27#endif
609342ff
DL
28
29#include <guasi.h>
30#include <guasi_syscalls.h>
31
32#ifdef GFIO_DEBUG
33#define GDBG_PRINT(a) printf a
34#else
35#define GDBG_PRINT(a) (void) 0
36#endif
37
609342ff
DL
38struct guasi_data {
39 guasi_t hctx;
40 int max_reqs;
41 guasi_req_t *reqs;
42 struct io_u **io_us;
46eaa157 43 int queued_nr;
609342ff
DL
44 int reqs_nr;
45};
46
47static int fio_guasi_prep(struct thread_data fio_unused *td, struct io_u *io_u)
48{
609342ff
DL
49
50 GDBG_PRINT(("fio_guasi_prep(%p)\n", io_u));
46eaa157 51 io_u->greq = NULL;
609342ff
DL
52
53 return 0;
54}
55
56static struct io_u *fio_guasi_event(struct thread_data *td, int event)
57{
58 struct guasi_data *ld = td->io_ops->data;
59 struct io_u *io_u;
60 struct guasi_reqinfo rinf;
61
62 GDBG_PRINT(("fio_guasi_event(%d)\n", event));
63 if (guasi_req_info(ld->reqs[event], &rinf) < 0) {
07257263 64 log_err("guasi_req_info(%d) FAILED!\n", event);
609342ff
DL
65 return NULL;
66 }
67 io_u = rinf.asid;
66b83d9a 68 io_u->error = EINPROGRESS;
609342ff 69 GDBG_PRINT(("fio_guasi_event(%d) -> %p\n", event, io_u));
66b83d9a 70 if (rinf.status == GUASI_STATUS_COMPLETE) {
609342ff 71 io_u->error = rinf.result;
66b83d9a
DL
72 if (io_u->ddir == DDIR_READ ||
73 io_u->ddir == DDIR_WRITE) {
74 io_u->error = 0;
75 if (rinf.result != (long) io_u->xfer_buflen) {
76 if (rinf.result >= 0)
77 io_u->resid = io_u->xfer_buflen - rinf.result;
78 else
79 io_u->error = rinf.error;
80 }
81 }
82 }
609342ff
DL
83
84 return io_u;
85}
86
e7d2e616
JA
87static int fio_guasi_getevents(struct thread_data *td, unsigned int min,
88 unsigned int max, struct timespec *t)
609342ff
DL
89{
90 struct guasi_data *ld = td->io_ops->data;
46eaa157 91 int n, r;
609342ff
DL
92 long timeo = -1;
93
94 GDBG_PRINT(("fio_guasi_getevents(%d, %d)\n", min, max));
95 if (min > ld->max_reqs)
96 min = ld->max_reqs;
97 if (max > ld->max_reqs)
98 max = ld->max_reqs;
99 if (t)
100 timeo = t->tv_sec * 1000L + t->tv_nsec / 1000000L;
46eaa157
DL
101 for (n = 0; n < ld->reqs_nr; n++)
102 guasi_req_free(ld->reqs[n]);
103 n = 0;
609342ff 104 do {
97c26cbe
DL
105 r = guasi_fetch(ld->hctx, ld->reqs + n, min - n,
106 max - n, timeo);
107 if (r < 0) {
07257263 108 log_err("guasi_fetch() FAILED! (%d)\n", r);
609342ff 109 break;
97c26cbe 110 }
609342ff
DL
111 n += r;
112 if (n >= min)
113 break;
114 } while (1);
46eaa157 115 ld->reqs_nr = n;
609342ff
DL
116 GDBG_PRINT(("fio_guasi_getevents() -> %d\n", n));
117
118 return n;
119}
120
121static int fio_guasi_queue(struct thread_data *td, struct io_u *io_u)
122{
123 struct guasi_data *ld = td->io_ops->data;
124
7101d9c2
JA
125 fio_ro_check(td, io_u);
126
609342ff 127 GDBG_PRINT(("fio_guasi_queue(%p)\n", io_u));
46eaa157 128 if (ld->queued_nr == (int) td->o.iodepth)
609342ff
DL
129 return FIO_Q_BUSY;
130
46eaa157
DL
131 ld->io_us[ld->queued_nr] = io_u;
132 ld->queued_nr++;
609342ff
DL
133 return FIO_Q_QUEUED;
134}
135
97c26cbe 136static void fio_guasi_queued(struct thread_data *td, struct io_u **io_us, int nr)
609342ff 137{
97c26cbe
DL
138 int i;
139 struct io_u *io_u;
609342ff 140 struct timeval now;
609342ff 141
12d9d841
JA
142 if (!fio_fill_issue_time(td))
143 return;
144
838bc709 145 io_u_mark_submit(td, nr);
609342ff 146 fio_gettime(&now, NULL);
97c26cbe
DL
147 for (i = 0; i < nr; i++) {
148 io_u = io_us[i];
149 memcpy(&io_u->issue_time, &now, sizeof(now));
150 io_u_queued(td, io_u);
151 }
609342ff
DL
152}
153
154static int fio_guasi_commit(struct thread_data *td)
155{
156 struct guasi_data *ld = td->io_ops->data;
157 int i;
158 struct io_u *io_u;
159 struct fio_file *f;
160
d6c6810f 161 GDBG_PRINT(("fio_guasi_commit(%d)\n", ld->queued_nr));
46eaa157 162 for (i = 0; i < ld->queued_nr; i++) {
609342ff 163 io_u = ld->io_us[i];
d6c6810f 164 GDBG_PRINT(("fio_guasi_commit(%d) --> %p\n", i, io_u));
609342ff
DL
165 f = io_u->file;
166 io_u->greq = NULL;
167 if (io_u->ddir == DDIR_READ)
168 io_u->greq = guasi__pread(ld->hctx, ld, io_u, 0,
169 f->fd, io_u->xfer_buf, io_u->xfer_buflen,
170 io_u->offset);
171 else if (io_u->ddir == DDIR_WRITE)
172 io_u->greq = guasi__pwrite(ld->hctx, ld, io_u, 0,
173 f->fd, io_u->xfer_buf, io_u->xfer_buflen,
174 io_u->offset);
5f9099ea 175 else if (ddir_sync(io_u->ddir))
609342ff
DL
176 io_u->greq = guasi__fsync(ld->hctx, ld, io_u, 0, f->fd);
177 else {
07257263 178 log_err("fio_guasi_commit() FAILED: unknow request %d\n",
66b83d9a 179 io_u->ddir);
609342ff 180 }
97c26cbe 181 if (io_u->greq == NULL) {
07257263 182 log_err("fio_guasi_commit() FAILED: submit failed (%s)\n",
d6c6810f 183 strerror(errno));
46eaa157
DL
184 return -1;
185 }
609342ff 186 }
97c26cbe 187 fio_guasi_queued(td, ld->io_us, i);
46eaa157 188 ld->queued_nr = 0;
609342ff
DL
189 GDBG_PRINT(("fio_guasi_commit() -> %d\n", i));
190
191 return 0;
192}
193
ffa59cea
JA
194static int fio_guasi_cancel(struct thread_data fio_unused *td,
195 struct io_u *io_u)
609342ff 196{
46eaa157
DL
197 GDBG_PRINT(("fio_guasi_cancel(%p) req=%p\n", io_u, io_u->greq));
198 if (io_u->greq != NULL)
199 guasi_req_cancel(io_u->greq);
609342ff 200
46eaa157 201 return 0;
609342ff
DL
202}
203
204static void fio_guasi_cleanup(struct thread_data *td)
205{
206 struct guasi_data *ld = td->io_ops->data;
8999fe9a 207 int n;
609342ff 208
46eaa157 209 GDBG_PRINT(("fio_guasi_cleanup(%p)\n", ld));
609342ff 210 if (ld) {
8999fe9a
DL
211 for (n = 0; n < ld->reqs_nr; n++)
212 guasi_req_free(ld->reqs[n]);
609342ff
DL
213 guasi_free(ld->hctx);
214 free(ld->reqs);
215 free(ld->io_us);
216 free(ld);
609342ff 217 }
46eaa157 218 GDBG_PRINT(("fio_guasi_cleanup(%p) DONE\n", ld));
609342ff
DL
219}
220
221static int fio_guasi_init(struct thread_data *td)
222{
223 int maxthr;
224 struct guasi_data *ld = malloc(sizeof(*ld));
225
46eaa157 226 GDBG_PRINT(("fio_guasi_init(): depth=%d\n", td->o.iodepth));
609342ff 227 memset(ld, 0, sizeof(*ld));
46eaa157 228 maxthr = td->o.iodepth > GFIO_MIN_THREADS ? td->o.iodepth: GFIO_MIN_THREADS;
d6c6810f
DL
229 if (maxthr > GFIO_MAX_THREADS)
230 maxthr = GFIO_MAX_THREADS;
0798ba36 231 if ((ld->hctx = guasi_create(GFIO_MIN_THREADS, maxthr, 1)) == NULL) {
609342ff
DL
232 td_verror(td, errno, "guasi_create");
233 free(ld);
234 return 1;
235 }
46eaa157 236 ld->max_reqs = td->o.iodepth;
609342ff
DL
237 ld->reqs = malloc(ld->max_reqs * sizeof(guasi_req_t));
238 ld->io_us = malloc(ld->max_reqs * sizeof(struct io_u *));
239 memset(ld->io_us, 0, ld->max_reqs * sizeof(struct io_u *));
46eaa157 240 ld->queued_nr = 0;
609342ff
DL
241 ld->reqs_nr = 0;
242
243 td->io_ops->data = ld;
46eaa157 244 GDBG_PRINT(("fio_guasi_init(): depth=%d -> %p\n", td->o.iodepth, ld));
609342ff
DL
245
246 return 0;
247}
248
249static struct ioengine_ops ioengine = {
250 .name = "guasi",
251 .version = FIO_IOOPS_VERSION,
252 .init = fio_guasi_init,
253 .prep = fio_guasi_prep,
254 .queue = fio_guasi_queue,
255 .commit = fio_guasi_commit,
256 .cancel = fio_guasi_cancel,
257 .getevents = fio_guasi_getevents,
258 .event = fio_guasi_event,
259 .cleanup = fio_guasi_cleanup,
260 .open_file = generic_open_file,
261 .close_file = generic_close_file,
df9c26b1 262 .get_file_size = generic_get_file_size,
609342ff
DL
263};
264
609342ff
DL
265static void fio_init fio_guasi_register(void)
266{
267 register_ioengine(&ioengine);
268}
269
270static void fio_exit fio_guasi_unregister(void)
271{
272 unregister_ioengine(&ioengine);
273}
274