c79b6f11146ff5ed7844f54da6ee03c3fbf971ac
[fio.git] / engines / skeleton_external.c
1 /*
2  * Skeleton for a sample external io engine
3  *
4  * Should be compiled with:
5  *
6  * gcc -Wall -O2 -g -D_GNU_SOURCE -include ../config-host.h -shared -rdynamic -fPIC -o skeleton_external.o skeleton_external.c
7  * (also requires -D_GNU_SOURCE -DCONFIG_STRSEP on Linux)
8  *
9  */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <assert.h>
15
16 #include "../fio.h"
17 #include "../optgroup.h"
18
19 /*
20  * The core of the module is identical to the ones included with fio,
21  * read those. You cannot use register_ioengine() and unregister_ioengine()
22  * for external modules, they should be gotten through dlsym()
23  */
24
25 /*
26  * The io engine can define its own options within the io engine source.
27  * The option member must not be at offset 0, due to the way fio parses
28  * the given option. Just add a padding pointer unless the io engine has
29  * something usable.
30  */
31 struct fio_skeleton_options {
32         void *pad; /* avoid ->off1 of fio_option becomes 0 */
33         unsigned int dummy;
34 };
35
36 static struct fio_option options[] = {
37         {
38                 .name   = "dummy",
39                 .lname  = "ldummy",
40                 .type   = FIO_OPT_STR_SET,
41                 .off1   = offsetof(struct fio_skeleton_options, dummy),
42                 .help   = "Set dummy",
43                 .category = FIO_OPT_C_ENGINE, /* always use this */
44                 .group  = FIO_OPT_G_INVALID, /* this can be different */
45         },
46         {
47                 .name   = NULL,
48         },
49 };
50
51 /*
52  * The ->event() hook is called to match an event number with an io_u.
53  * After the core has called ->getevents() and it has returned eg 3,
54  * the ->event() hook must return the 3 events that have completed for
55  * subsequent calls to ->event() with [0-2]. Required.
56  */
57 static struct io_u *fio_skeleton_event(struct thread_data *td, int event)
58 {
59         return NULL;
60 }
61
62 /*
63  * The ->getevents() hook is used to reap completion events from an async
64  * io engine. It returns the number of completed events since the last call,
65  * which may then be retrieved by calling the ->event() hook with the event
66  * numbers. Required.
67  */
68 static int fio_skeleton_getevents(struct thread_data *td, unsigned int min,
69                                   unsigned int max, const struct timespec *t)
70 {
71         return 0;
72 }
73
74 /*
75  * The ->cancel() hook attempts to cancel the io_u. Only relevant for
76  * async io engines, and need not be supported.
77  */
78 static int fio_skeleton_cancel(struct thread_data *td, struct io_u *io_u)
79 {
80         return 0;
81 }
82
83 /*
84  * The ->queue() hook is responsible for initiating io on the io_u
85  * being passed in. If the io engine is a synchronous one, io may complete
86  * before ->queue() returns. Required.
87  *
88  * The io engine must transfer in the direction noted by io_u->ddir
89  * to the buffer pointed to by io_u->xfer_buf for as many bytes as
90  * io_u->xfer_buflen. Residual data count may be set in io_u->resid
91  * for a short read/write.
92  */
93 static enum fio_q_status fio_skeleton_queue(struct thread_data *td,
94                                             struct io_u *io_u)
95 {
96         /*
97          * Double sanity check to catch errant write on a readonly setup
98          */
99         fio_ro_check(td, io_u);
100
101         /*
102          * Could return FIO_Q_QUEUED for a queued request,
103          * FIO_Q_COMPLETED for a completed request, and FIO_Q_BUSY
104          * if we could queue no more at this point (you'd have to
105          * define ->commit() to handle that.
106          */
107         return FIO_Q_COMPLETED;
108 }
109
110 /*
111  * The ->prep() function is called for each io_u prior to being submitted
112  * with ->queue(). This hook allows the io engine to perform any
113  * preparatory actions on the io_u, before being submitted. Not required.
114  */
115 static int fio_skeleton_prep(struct thread_data *td, struct io_u *io_u)
116 {
117         return 0;
118 }
119
120 /*
121  * The init function is called once per thread/process, and should set up
122  * any structures that this io engine requires to keep track of io. Not
123  * required.
124  */
125 static int fio_skeleton_init(struct thread_data *td)
126 {
127         return 0;
128 }
129
130 /*
131  * This is paired with the ->init() function and is called when a thread is
132  * done doing io. Should tear down anything setup by the ->init() function.
133  * Not required.
134  */
135 static void fio_skeleton_cleanup(struct thread_data *td)
136 {
137 }
138
139 /*
140  * Hook for opening the given file. Unless the engine has special
141  * needs, it usually just provides generic_open_file() as the handler.
142  */
143 static int fio_skeleton_open(struct thread_data *td, struct fio_file *f)
144 {
145         return generic_open_file(td, f);
146 }
147
148 /*
149  * Hook for closing a file. See fio_skeleton_open().
150  */
151 static int fio_skeleton_close(struct thread_data *td, struct fio_file *f)
152 {
153         return generic_close_file(td, f);
154 }
155
156 /*
157  * Hook for getting the zoned model of a zoned block device for zonemode=zbd.
158  * The zoned model can be one of (see zbd_types.h):
159  * - ZBD_IGNORE: skip regular files
160  * - ZBD_NONE: regular block device (zone emulation will be used)
161  * - ZBD_HOST_AWARE: host aware zoned block device
162  * - ZBD_HOST_MANAGED: host managed zoned block device
163  */
164 static int fio_skeleton_get_zoned_model(struct thread_data *td,
165                         struct fio_file *f, enum zbd_zoned_model *model)
166 {
167         *model = ZBD_NONE;
168         return 0;
169 }
170
171 /*
172  * Hook called for getting zone information of a ZBD_HOST_AWARE or
173  * ZBD_HOST_MANAGED zoned block device. Up to @nr_zones zone information
174  * structures can be reported using the array zones for zones starting from
175  * @offset. The number of zones reported must be returned or a negative error
176  * code in case of error.
177  */
178 static int fio_skeleton_report_zones(struct thread_data *td, struct fio_file *f,
179                                      uint64_t offset, struct zbd_zone *zones,
180                                      unsigned int nr_zones)
181 {
182         return 0;
183 }
184
185 /*
186  * Hook called for resetting the write pointer position of zones of a
187  * ZBD_HOST_AWARE or ZBD_HOST_MANAGED zoned block device. The write pointer
188  * position of all zones in the range @offset..@offset + @length must be reset.
189  */
190 static int fio_skeleton_reset_wp(struct thread_data *td, struct fio_file *f,
191                                  uint64_t offset, uint64_t length)
192 {
193         return 0;
194 }
195
196 /*
197  * Hook called for getting the maximum number of open zones for a
198  * ZBD_HOST_MANAGED zoned block device.
199  * A @max_open_zones value set to zero means no limit.
200  */
201 static int fio_skeleton_get_max_open_zones(struct thread_data *td,
202                                            struct fio_file *f,
203                                            unsigned int *max_open_zones)
204 {
205         return 0;
206 }
207
208 /*
209  * Note that the structure is exported, so that fio can get it via
210  * dlsym(..., "ioengine"); for (and only for) external engines.
211  */
212 struct ioengine_ops ioengine = {
213         .name           = "engine_name",
214         .version        = FIO_IOOPS_VERSION,
215         .init           = fio_skeleton_init,
216         .prep           = fio_skeleton_prep,
217         .queue          = fio_skeleton_queue,
218         .cancel         = fio_skeleton_cancel,
219         .getevents      = fio_skeleton_getevents,
220         .event          = fio_skeleton_event,
221         .cleanup        = fio_skeleton_cleanup,
222         .open_file      = fio_skeleton_open,
223         .close_file     = fio_skeleton_close,
224         .get_zoned_model = fio_skeleton_get_zoned_model,
225         .report_zones   = fio_skeleton_report_zones,
226         .reset_wp       = fio_skeleton_reset_wp,
227         .get_max_open_zones = fio_skeleton_get_max_open_zones,
228         .options        = options,
229         .option_struct_size     = sizeof(struct fio_skeleton_options),
230 };