Turn the CPU burner into a real io engine
[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 min_events,
28                               int fio_unused max, struct timespec fio_unused *t)
29 {
30         struct null_data *nd = td->io_ops->data;
31         int ret = 0;
32         
33         if (min_events) {
34                 ret = nd->events;
35                 nd->events = 0;
36         }
37
38         return ret;
39 }
40
41 static int fio_null_commit(struct thread_data *td)
42 {
43         struct null_data *nd = td->io_ops->data;
44
45         nd->events += nd->queued;
46         nd->queued = 0;
47         return 0;
48 }
49
50 static int fio_null_queue(struct thread_data fio_unused *td, struct io_u *io_u)
51 {
52         struct null_data *nd = td->io_ops->data;
53
54         if (td->io_ops->flags & FIO_SYNCIO)
55                 return FIO_Q_COMPLETED;
56
57         nd->io_us[nd->queued++] = io_u;
58         return FIO_Q_QUEUED;
59 }
60
61 static int fio_null_setup(struct thread_data *td)
62 {
63         struct fio_file *f;
64         int i;
65
66         if (!td->total_file_size) {
67                 log_err("fio: need size= set\n");
68                 return 1;
69         }
70
71         td->io_size = td->total_file_size;
72         td->total_io_size = td->io_size;
73
74         for_each_file(td, f, i) {
75                 f->real_file_size = td->total_io_size / td->nr_files;
76                 f->file_size = f->real_file_size;
77         }
78
79         return 0;
80 }
81
82 static int fio_null_open(struct thread_data fio_unused *td,
83                          struct fio_file fio_unused *f)
84 {
85         f->fd = 0;
86         return 0;
87 }
88
89 static void fio_null_cleanup(struct thread_data *td)
90 {
91         struct null_data *nd = td->io_ops->data;
92
93         if (nd) {
94                 if (nd->io_us)
95                         free(nd->io_us);
96                 free(nd);
97                 td->io_ops->data = NULL;
98         }
99 }
100
101 static int fio_null_init(struct thread_data *td)
102 {
103         struct null_data *nd = malloc(sizeof(*nd));
104
105         memset(nd, 0, sizeof(*nd));
106
107         if (td->iodepth != 1) {
108                 nd->io_us = malloc(td->iodepth * sizeof(struct io_u *));
109                 memset(nd->io_us, 0, td->iodepth * sizeof(struct io_u *));
110         } else
111                 td->io_ops->flags |= FIO_SYNCIO;
112
113         td->io_ops->data = nd;
114         return 0;
115 }
116
117 static struct ioengine_ops ioengine = {
118         .name           = "null",
119         .version        = FIO_IOOPS_VERSION,
120         .setup          = fio_null_setup,
121         .queue          = fio_null_queue,
122         .commit         = fio_null_commit,
123         .getevents      = fio_null_getevents,
124         .event          = fio_null_event,
125         .init           = fio_null_init,
126         .cleanup        = fio_null_cleanup,
127         .open_file      = fio_null_open,
128         .flags          = FIO_DISKLESSIO,
129 };
130
131 static void fio_init fio_null_register(void)
132 {
133         register_ioengine(&ioengine);
134 }
135
136 static void fio_exit fio_null_unregister(void)
137 {
138         unregister_ioengine(&ioengine);
139 }