engines/null: fill issue_time during commit
[fio.git] / engines / null.c
CommitLineData
a94ea28b 1/*
da751ca9
JA
2 * null engine
3 *
4 * IO engine that doesn't do any real IO transfers, it just pretends to.
5 * The main purpose is to test fio itself.
a94ea28b 6 *
46a67478
DG
7 * It also can act as external C++ engine - compiled with:
8 *
cef0a835 9 * g++ -O2 -g -shared -rdynamic -fPIC -o cpp_null null.c \
c822572d 10 * -include ../config-host.h -DFIO_EXTERNAL_ENGINE
966fcbd4 11 *
12 * to test it execute:
13 *
14 * LD_LIBRARY_PATH=./engines ./fio examples/cpp_null.fio
46a67478 15 *
a94ea28b 16 */
a94ea28b 17#include <stdlib.h>
a94ea28b
JA
18#include <assert.h>
19
20#include "../fio.h"
a94ea28b 21
65afa5f2
JA
22struct null_data {
23 struct io_u **io_us;
24 int queued;
25 int events;
26};
27
966fcbd4 28static struct io_u *null_event(struct null_data *nd, int event)
65afa5f2 29{
65afa5f2
JA
30 return nd->io_us[event];
31}
32
966fcbd4 33static int null_getevents(struct null_data *nd, unsigned int min_events,
34 unsigned int fio_unused max,
35 const struct timespec fio_unused *t)
65afa5f2 36{
7401c088 37 int ret = 0;
966fcbd4 38
7401c088
JA
39 if (min_events) {
40 ret = nd->events;
41 nd->events = 0;
42 }
65afa5f2 43
65afa5f2
JA
44 return ret;
45}
46
56b6bc25
VF
47static void null_queued(struct thread_data *td, struct null_data *nd)
48{
49 struct timespec now;
50
51 if (!fio_fill_issue_time(td))
52 return;
53
54 fio_gettime(&now, NULL);
55
56 for (int i = 0; i < nd->queued; i++) {
57 struct io_u *io_u = nd->io_us[i];
58
59 memcpy(&io_u->issue_time, &now, sizeof(now));
60 io_u_queued(td, io_u);
61 }
62}
63
966fcbd4 64static int null_commit(struct thread_data *td, struct null_data *nd)
65afa5f2 65{
ed8bd849 66 if (!nd->events) {
56b6bc25
VF
67 null_queued(td, nd);
68
46a67478 69#ifndef FIO_EXTERNAL_ENGINE
838bc709 70 io_u_mark_submit(td, nd->queued);
46a67478 71#endif
ed8bd849
JA
72 nd->events = nd->queued;
73 nd->queued = 0;
74 }
75
65afa5f2
JA
76 return 0;
77}
78
2e4ef4fb
JA
79static enum fio_q_status null_queue(struct thread_data *td,
80 struct null_data *nd, struct io_u *io_u)
a94ea28b 81{
7101d9c2
JA
82 fio_ro_check(td, io_u);
83
65afa5f2
JA
84 if (td->io_ops->flags & FIO_SYNCIO)
85 return FIO_Q_COMPLETED;
ed8bd849
JA
86 if (nd->events)
87 return FIO_Q_BUSY;
65afa5f2
JA
88
89 nd->io_us[nd->queued++] = io_u;
90 return FIO_Q_QUEUED;
a94ea28b
JA
91}
92
966fcbd4 93static int null_open(struct null_data fio_unused *nd,
94 struct fio_file fio_unused *f)
b5af8293
JA
95{
96 return 0;
97}
98
966fcbd4 99static void null_cleanup(struct null_data *nd)
65afa5f2 100{
65afa5f2 101 if (nd) {
02a3d83f 102 free(nd->io_us);
65afa5f2 103 free(nd);
65afa5f2
JA
104 }
105}
106
7746976c 107static struct null_data *null_init(struct thread_data *td)
65afa5f2 108{
7746976c 109 struct null_data *nd = (struct null_data *) malloc(sizeof(*nd));
65afa5f2
JA
110
111 memset(nd, 0, sizeof(*nd));
112
2dc1bbeb 113 if (td->o.iodepth != 1) {
46a67478 114 nd->io_us = (struct io_u **) malloc(td->o.iodepth * sizeof(struct io_u *));
2dc1bbeb 115 memset(nd->io_us, 0, td->o.iodepth * sizeof(struct io_u *));
65afa5f2
JA
116 } else
117 td->io_ops->flags |= FIO_SYNCIO;
118
7746976c 119 return nd;
65afa5f2
JA
120}
121
46a67478 122#ifndef __cplusplus
966fcbd4 123
124static struct io_u *fio_null_event(struct thread_data *td, int event)
125{
ca65714c 126 return null_event(td->io_ops_data, event);
966fcbd4 127}
128
129static int fio_null_getevents(struct thread_data *td, unsigned int min_events,
130 unsigned int max, const struct timespec *t)
131{
ca65714c 132 struct null_data *nd = td->io_ops_data;
966fcbd4 133 return null_getevents(nd, min_events, max, t);
134}
135
136static int fio_null_commit(struct thread_data *td)
137{
ca65714c 138 return null_commit(td, td->io_ops_data);
966fcbd4 139}
140
2e4ef4fb
JA
141static enum fio_q_status fio_null_queue(struct thread_data *td,
142 struct io_u *io_u)
966fcbd4 143{
ca65714c 144 return null_queue(td, td->io_ops_data, io_u);
966fcbd4 145}
146
147static int fio_null_open(struct thread_data *td, struct fio_file *f)
148{
ca65714c 149 return null_open(td->io_ops_data, f);
966fcbd4 150}
151
152static void fio_null_cleanup(struct thread_data *td)
153{
ca65714c 154 null_cleanup(td->io_ops_data);
966fcbd4 155}
156
157static int fio_null_init(struct thread_data *td)
158{
7746976c
TK
159 td->io_ops_data = null_init(td);
160 assert(td->io_ops_data);
161 return 0;
966fcbd4 162}
163
a94ea28b
JA
164static struct ioengine_ops ioengine = {
165 .name = "null",
166 .version = FIO_IOOPS_VERSION,
a94ea28b 167 .queue = fio_null_queue,
65afa5f2
JA
168 .commit = fio_null_commit,
169 .getevents = fio_null_getevents,
170 .event = fio_null_event,
171 .init = fio_null_init,
172 .cleanup = fio_null_cleanup,
b5af8293 173 .open_file = fio_null_open,
5c57c084 174 .flags = FIO_DISKLESSIO | FIO_FAKEIO,
a94ea28b
JA
175};
176
177static void fio_init fio_null_register(void)
178{
179 register_ioengine(&ioengine);
180}
181
182static void fio_exit fio_null_unregister(void)
183{
184 unregister_ioengine(&ioengine);
185}
46a67478
DG
186
187#else
188
189#ifdef FIO_EXTERNAL_ENGINE
966fcbd4 190
191struct NullData {
192 NullData(struct thread_data *td)
193 {
7746976c
TK
194 impl_ = null_init(td);
195 assert(impl_);
966fcbd4 196 }
197
198 ~NullData()
199 {
200 null_cleanup(impl_);
201 }
202
203 static NullData *get(struct thread_data *td)
204 {
205 return reinterpret_cast<NullData *>(td->io_ops_data);
206 }
207
208 io_u *fio_null_event(struct thread_data *, int event)
209 {
210 return null_event(impl_, event);
211 }
212
213 int fio_null_getevents(struct thread_data *, unsigned int min_events,
214 unsigned int max, const struct timespec *t)
215 {
216 return null_getevents(impl_, min_events, max, t);
217 }
218
219 int fio_null_commit(struct thread_data *td)
220 {
221 return null_commit(td, impl_);
222 }
223
cef0a835 224 fio_q_status fio_null_queue(struct thread_data *td, struct io_u *io_u)
966fcbd4 225 {
226 return null_queue(td, impl_, io_u);
227 }
228
229 int fio_null_open(struct thread_data *, struct fio_file *f)
230 {
231 return null_open(impl_, f);
232 }
233
7caf10f1 234private:
966fcbd4 235 struct null_data *impl_;
236};
237
46a67478 238extern "C" {
966fcbd4 239
240static struct io_u *fio_null_event(struct thread_data *td, int event)
241{
242 return NullData::get(td)->fio_null_event(td, event);
243}
244
245static int fio_null_getevents(struct thread_data *td, unsigned int min_events,
246 unsigned int max, const struct timespec *t)
247{
248 return NullData::get(td)->fio_null_getevents(td, min_events, max, t);
249}
250
251static int fio_null_commit(struct thread_data *td)
252{
253 return NullData::get(td)->fio_null_commit(td);
254}
255
cef0a835 256static fio_q_status fio_null_queue(struct thread_data *td, struct io_u *io_u)
966fcbd4 257{
258 return NullData::get(td)->fio_null_queue(td, io_u);
259}
260
261static int fio_null_open(struct thread_data *td, struct fio_file *f)
262{
263 return NullData::get(td)->fio_null_open(td, f);
264}
265
266static int fio_null_init(struct thread_data *td)
267{
268 td->io_ops_data = new NullData(td);
269 return 0;
270}
271
272static void fio_null_cleanup(struct thread_data *td)
273{
274 delete NullData::get(td);
275}
276
247f299a 277static struct ioengine_ops ioengine;
8d6ecac2
JA
278void get_ioengine(struct ioengine_ops **ioengine_ptr)
279{
247f299a
TK
280 *ioengine_ptr = &ioengine;
281
282 ioengine.name = "cpp_null";
283 ioengine.version = FIO_IOOPS_VERSION;
284 ioengine.queue = fio_null_queue;
285 ioengine.commit = fio_null_commit;
286 ioengine.getevents = fio_null_getevents;
287 ioengine.event = fio_null_event;
288 ioengine.init = fio_null_init;
289 ioengine.cleanup = fio_null_cleanup;
290 ioengine.open_file = fio_null_open;
291 ioengine.flags = FIO_DISKLESSIO | FIO_FAKEIO;
46a67478
DG
292}
293}
294#endif /* FIO_EXTERNAL_ENGINE */
295
296#endif /* __cplusplus */