null engine: update to support queuing
[fio.git] / engines / null.c
1 /*
2  * null engine - doesn't do any transfers. Used to test fio.
3  *
4  */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <assert.h>
10
11 #include "../fio.h"
12 #include "../os.h"
13
14 struct null_data {
15         struct io_u **io_us;
16         int queued;
17         int events;
18 };
19
20 static struct io_u *fio_null_event(struct thread_data *td, int event)
21 {
22         struct null_data *nd = td->io_ops->data;
23
24         return nd->io_us[event];
25 }
26
27 static int fio_null_getevents(struct thread_data *td, int fio_unused min,
28                               int fio_unused max, struct timespec fio_unused *t)
29 {
30         struct null_data *nd = td->io_ops->data;
31         int ret;
32
33         ret = nd->events;
34         nd->events = 0;
35         return ret;
36 }
37
38 static int fio_null_commit(struct thread_data *td)
39 {
40         struct null_data *nd = td->io_ops->data;
41
42         nd->events = nd->queued;
43         nd->queued = 0;
44         return 0;
45 }
46
47 static int fio_null_queue(struct thread_data fio_unused *td, struct io_u *io_u)
48 {
49         struct null_data *nd = td->io_ops->data;
50
51         if (td->io_ops->flags & FIO_SYNCIO)
52                 return FIO_Q_COMPLETED;
53
54         nd->io_us[nd->queued++] = io_u;
55         return FIO_Q_QUEUED;
56 }
57
58 static int fio_null_setup(struct thread_data *td)
59 {
60         struct fio_file *f;
61         int i;
62
63         if (!td->total_file_size) {
64                 log_err("fio: need size= set\n");
65                 return 1;
66         }
67
68         td->io_size = td->total_file_size;
69         td->total_io_size = td->io_size;
70
71         for_each_file(td, f, i) {
72                 f->real_file_size = td->total_io_size / td->nr_files;
73                 f->file_size = f->real_file_size;
74         }
75
76         return 0;
77 }
78
79 static int fio_null_open(struct thread_data fio_unused *td,
80                          struct fio_file fio_unused *f)
81 {
82         f->fd = 0;
83         return 0;
84 }
85
86 static void fio_null_cleanup(struct thread_data *td)
87 {
88         struct null_data *nd = td->io_ops->data;
89
90         if (nd) {
91                 if (nd->io_us)
92                         free(nd->io_us);
93                 free(nd);
94                 td->io_ops->data = NULL;
95         }
96 }
97
98 static int fio_null_init(struct thread_data *td)
99 {
100         struct null_data *nd = malloc(sizeof(*nd));
101
102         memset(nd, 0, sizeof(*nd));
103
104         if (td->iodepth != 1) {
105                 nd->io_us = malloc(td->iodepth * sizeof(struct io_u *));
106                 memset(nd->io_us, 0, td->iodepth * sizeof(struct io_u *));
107         } else
108                 td->io_ops->flags |= FIO_SYNCIO;
109
110         td->io_ops->data = nd;
111         return 0;
112 }
113
114 static struct ioengine_ops ioengine = {
115         .name           = "null",
116         .version        = FIO_IOOPS_VERSION,
117         .setup          = fio_null_setup,
118         .queue          = fio_null_queue,
119         .commit         = fio_null_commit,
120         .getevents      = fio_null_getevents,
121         .event          = fio_null_event,
122         .init           = fio_null_init,
123         .cleanup        = fio_null_cleanup,
124         .open_file      = fio_null_open,
125         .flags          = FIO_DISKLESSIO,
126 };
127
128 static void fio_init fio_null_register(void)
129 {
130         register_ioengine(&ioengine);
131 }
132
133 static void fio_exit fio_null_unregister(void)
134 {
135         unregister_ioengine(&ioengine);
136 }