configure: new --dynamic-libengines build option
[fio.git] / ioengines.c
1 /*
2  * The io parts of the fio tool, includes workers for sync and mmap'ed
3  * io, as well as both posix and linux libaio support.
4  *
5  * sync io is implemented on top of aio.
6  *
7  * This is not really specific to fio, if the get_io_u/put_io_u and
8  * structures was pulled into this as well it would be a perfectly
9  * generic io engine that could be used for other projects.
10  *
11  */
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <dlfcn.h>
16 #include <fcntl.h>
17 #include <assert.h>
18
19 #include "fio.h"
20 #include "diskutil.h"
21 #include "zbd.h"
22
23 static FLIST_HEAD(engine_list);
24
25 static bool check_engine_ops(struct ioengine_ops *ops)
26 {
27         if (ops->version != FIO_IOOPS_VERSION) {
28                 log_err("bad ioops version %d (want %d)\n", ops->version,
29                                                         FIO_IOOPS_VERSION);
30                 return true;
31         }
32
33         if (!ops->queue) {
34                 log_err("%s: no queue handler\n", ops->name);
35                 return true;
36         }
37
38         /*
39          * sync engines only need a ->queue()
40          */
41         if (ops->flags & FIO_SYNCIO)
42                 return false;
43
44         if (!ops->event || !ops->getevents) {
45                 log_err("%s: no event/getevents handler\n", ops->name);
46                 return true;
47         }
48
49         return false;
50 }
51
52 void unregister_ioengine(struct ioengine_ops *ops)
53 {
54         dprint(FD_IO, "ioengine %s unregistered\n", ops->name);
55         flist_del_init(&ops->list);
56 }
57
58 void register_ioengine(struct ioengine_ops *ops)
59 {
60         dprint(FD_IO, "ioengine %s registered\n", ops->name);
61         flist_add_tail(&ops->list, &engine_list);
62 }
63
64 static struct ioengine_ops *find_ioengine(const char *name)
65 {
66         struct ioengine_ops *ops;
67         struct flist_head *entry;
68
69         flist_for_each(entry, &engine_list) {
70                 ops = flist_entry(entry, struct ioengine_ops, list);
71                 if (!strcmp(name, ops->name))
72                         return ops;
73         }
74
75         return NULL;
76 }
77
78 #ifdef CONFIG_DYNAMIC_ENGINES
79 static void *dlopen_external(struct thread_data *td, const char *engine)
80 {
81         char engine_path[PATH_MAX];
82
83         sprintf(engine_path, "%s/lib%s.so", FIO_EXT_ENG_DIR, engine);
84
85         return dlopen(engine_path, RTLD_LAZY);
86 }
87 #else
88 #define dlopen_external(td, engine) (NULL)
89 #endif
90
91 static struct ioengine_ops *dlopen_ioengine(struct thread_data *td,
92                                             const char *engine_lib)
93 {
94         struct ioengine_ops *ops;
95         void *dlhandle;
96
97         dprint(FD_IO, "dload engine %s\n", engine_lib);
98
99         dlerror();
100         dlhandle = dlopen(engine_lib, RTLD_LAZY);
101         if (!dlhandle) {
102                 dlhandle = dlopen_external(td, engine_lib);
103                 if (!dlhandle) {
104                         td_vmsg(td, -1, dlerror(), "dlopen");
105                         return NULL;
106                 }
107         }
108
109         /*
110          * Unlike the included modules, external engines should have a
111          * non-static ioengine structure that we can reference.
112          */
113         ops = dlsym(dlhandle, engine_lib);
114         if (!ops)
115                 ops = dlsym(dlhandle, "ioengine");
116
117         /*
118          * For some external engines (like C++ ones) it is not that trivial
119          * to provide a non-static ionengine structure that we can reference.
120          * Instead we call a method which allocates the required ioengine
121          * structure.
122          */
123         if (!ops) {
124                 get_ioengine_t get_ioengine = dlsym(dlhandle, "get_ioengine");
125
126                 if (get_ioengine)
127                         get_ioengine(&ops);
128         }
129
130         if (!ops) {
131                 td_vmsg(td, -1, dlerror(), "dlsym");
132                 dlclose(dlhandle);
133                 return NULL;
134         }
135
136         td->io_ops_dlhandle = dlhandle;
137         return ops;
138 }
139
140 static struct ioengine_ops *__load_ioengine(const char *engine)
141 {
142         /*
143          * linux libaio has alias names, so convert to what we want
144          */
145         if (!strncmp(engine, "linuxaio", 8)) {
146                 dprint(FD_IO, "converting ioengine name: %s -> libaio\n",
147                        engine);
148                 engine = "libaio";
149         }
150
151         dprint(FD_IO, "load ioengine %s\n", engine);
152         return find_ioengine(engine);
153 }
154
155 struct ioengine_ops *load_ioengine(struct thread_data *td)
156 {
157         struct ioengine_ops *ops = NULL;
158         const char *name;
159
160         /*
161          * Use ->ioengine_so_path if an external ioengine path is specified.
162          * In this case, ->ioengine is "external" which also means the prefix
163          * for external ioengines "external:" is properly used.
164          */
165         name = td->o.ioengine_so_path ?: td->o.ioengine;
166
167         /*
168          * Try to load ->ioengine first, and if failed try to dlopen(3) either
169          * ->ioengine or ->ioengine_so_path.  This is redundant for an external
170          * ioengine with prefix, and also leaves the possibility of unexpected
171          * behavior (e.g. if the "external" ioengine exists), but we do this
172          * so as not to break job files not using the prefix.
173          */
174         ops = __load_ioengine(td->o.ioengine);
175         if (!ops)
176                 ops = dlopen_ioengine(td, name);
177
178         /*
179          * If ops is NULL, we failed to load ->ioengine, and also failed to
180          * dlopen(3) either ->ioengine or ->ioengine_so_path as a path.
181          */
182         if (!ops) {
183                 log_err("fio: engine %s not loadable\n", name);
184                 return NULL;
185         }
186
187         /*
188          * Check that the required methods are there.
189          */
190         if (check_engine_ops(ops))
191                 return NULL;
192
193         return ops;
194 }
195
196 /*
197  * For cleaning up an ioengine which never made it to init().
198  */
199 void free_ioengine(struct thread_data *td)
200 {
201         dprint(FD_IO, "free ioengine %s\n", td->io_ops->name);
202
203         if (td->eo && td->io_ops->options) {
204                 options_free(td->io_ops->options, td->eo);
205                 free(td->eo);
206                 td->eo = NULL;
207         }
208
209         if (td->io_ops_dlhandle) {
210                 dlclose(td->io_ops_dlhandle);
211                 td->io_ops_dlhandle = NULL;
212         }
213
214         td->io_ops = NULL;
215 }
216
217 void close_ioengine(struct thread_data *td)
218 {
219         dprint(FD_IO, "close ioengine %s\n", td->io_ops->name);
220
221         if (td->io_ops->cleanup) {
222                 td->io_ops->cleanup(td);
223                 td->io_ops_data = NULL;
224         }
225
226         free_ioengine(td);
227 }
228
229 int td_io_prep(struct thread_data *td, struct io_u *io_u)
230 {
231         dprint_io_u(io_u, "prep");
232         fio_ro_check(td, io_u);
233
234         lock_file(td, io_u->file, io_u->ddir);
235
236         if (td->io_ops->prep) {
237                 int ret = td->io_ops->prep(td, io_u);
238
239                 dprint(FD_IO, "prep: io_u %p: ret=%d\n", io_u, ret);
240
241                 if (ret)
242                         unlock_file(td, io_u->file);
243                 return ret;
244         }
245
246         return 0;
247 }
248
249 int td_io_getevents(struct thread_data *td, unsigned int min, unsigned int max,
250                     const struct timespec *t)
251 {
252         int r = 0;
253
254         /*
255          * For ioengine=rdma one side operation RDMA_WRITE or RDMA_READ,
256          * server side gets a message from the client
257          * side that the task is finished, and
258          * td->done is set to 1 after td_io_commit(). In this case,
259          * there is no need to reap complete event in server side.
260          */
261         if (td->done)
262                 return 0;
263
264         if (min > 0 && td->io_ops->commit) {
265                 r = td->io_ops->commit(td);
266                 if (r < 0)
267                         goto out;
268         }
269         if (max > td->cur_depth)
270                 max = td->cur_depth;
271         if (min > max)
272                 max = min;
273
274         r = 0;
275         if (max && td->io_ops->getevents)
276                 r = td->io_ops->getevents(td, min, max, t);
277 out:
278         if (r >= 0) {
279                 /*
280                  * Reflect that our submitted requests were retrieved with
281                  * whatever OS async calls are in the underlying engine.
282                  */
283                 td->io_u_in_flight -= r;
284                 io_u_mark_complete(td, r);
285         } else
286                 td_verror(td, r, "get_events");
287
288         dprint(FD_IO, "getevents: %d\n", r);
289         return r;
290 }
291
292 enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u)
293 {
294         const enum fio_ddir ddir = acct_ddir(io_u);
295         unsigned long long buflen = io_u->xfer_buflen;
296         enum fio_q_status ret;
297
298         dprint_io_u(io_u, "queue");
299         fio_ro_check(td, io_u);
300
301         assert((io_u->flags & IO_U_F_FLIGHT) == 0);
302         io_u_set(td, io_u, IO_U_F_FLIGHT);
303
304         /*
305          * If overlap checking was enabled in offload mode we
306          * can release this lock that was acquired when we
307          * started the overlap check because the IO_U_F_FLIGHT
308          * flag is now set
309          */
310         if (td_offload_overlap(td))
311                 pthread_mutex_unlock(&overlap_check);
312
313         assert(fio_file_open(io_u->file));
314
315         /*
316          * If using a write iolog, store this entry.
317          */
318         log_io_u(td, io_u);
319
320         io_u->error = 0;
321         io_u->resid = 0;
322
323         if (td_ioengine_flagged(td, FIO_SYNCIO) ||
324                 (td_ioengine_flagged(td, FIO_ASYNCIO_SYNC_TRIM) && 
325                 io_u->ddir == DDIR_TRIM)) {
326                 if (fio_fill_issue_time(td))
327                         fio_gettime(&io_u->issue_time, NULL);
328
329                 /*
330                  * only used for iolog
331                  */
332                 if (td->o.read_iolog_file)
333                         memcpy(&td->last_issue, &io_u->issue_time,
334                                         sizeof(io_u->issue_time));
335         }
336
337
338         if (ddir_rw(ddir)) {
339                 if (!(io_u->flags & IO_U_F_VER_LIST)) {
340                         td->io_issues[ddir]++;
341                         td->io_issue_bytes[ddir] += buflen;
342                 }
343                 td->rate_io_issue_bytes[ddir] += buflen;
344         }
345
346         ret = td->io_ops->queue(td, io_u);
347         zbd_queue_io_u(io_u, ret);
348
349         unlock_file(td, io_u->file);
350
351         if (ret == FIO_Q_BUSY && ddir_rw(ddir)) {
352                 td->io_issues[ddir]--;
353                 td->io_issue_bytes[ddir] -= buflen;
354                 td->rate_io_issue_bytes[ddir] -= buflen;
355                 io_u_clear(td, io_u, IO_U_F_FLIGHT);
356         }
357
358         /*
359          * If an error was seen and the io engine didn't propagate it
360          * back to 'td', do so.
361          */
362         if (io_u->error && !td->error)
363                 td_verror(td, io_u->error, "td_io_queue");
364
365         /*
366          * Add warning for O_DIRECT so that users have an easier time
367          * spotting potentially bad alignment. If this triggers for the first
368          * IO, then it's likely an alignment problem or because the host fs
369          * does not support O_DIRECT
370          */
371         if (io_u->error == EINVAL && td->io_issues[io_u->ddir & 1] == 1 &&
372             td->o.odirect) {
373
374                 log_info("fio: first direct IO errored. File system may not "
375                          "support direct IO, or iomem_align= is bad, or "
376                          "invalid block size. Try setting direct=0.\n");
377         }
378
379         if (zbd_unaligned_write(io_u->error) &&
380             td->io_issues[io_u->ddir & 1] == 1 &&
381             td->o.zone_mode != ZONE_MODE_ZBD) {
382                 log_info("fio: first I/O failed. If %s is a zoned block device, consider --zonemode=zbd\n",
383                          io_u->file->file_name);
384         }
385
386         if (!td->io_ops->commit) {
387                 io_u_mark_submit(td, 1);
388                 io_u_mark_complete(td, 1);
389                 zbd_put_io_u(io_u);
390         }
391
392         if (ret == FIO_Q_COMPLETED) {
393                 if (ddir_rw(io_u->ddir) ||
394                     (ddir_sync(io_u->ddir) && td->runstate != TD_FSYNCING)) {
395                         io_u_mark_depth(td, 1);
396                         td->ts.total_io_u[io_u->ddir]++;
397                 }
398         } else if (ret == FIO_Q_QUEUED) {
399                 td->io_u_queued++;
400
401                 if (ddir_rw(io_u->ddir) ||
402                     (ddir_sync(io_u->ddir) && td->runstate != TD_FSYNCING))
403                         td->ts.total_io_u[io_u->ddir]++;
404
405                 if (td->io_u_queued >= td->o.iodepth_batch)
406                         td_io_commit(td);
407         }
408
409         if (!td_ioengine_flagged(td, FIO_SYNCIO) &&
410                 (!td_ioengine_flagged(td, FIO_ASYNCIO_SYNC_TRIM) ||
411                  io_u->ddir != DDIR_TRIM)) {
412                 if (fio_fill_issue_time(td))
413                         fio_gettime(&io_u->issue_time, NULL);
414
415                 /*
416                  * only used for iolog
417                  */
418                 if (td->o.read_iolog_file)
419                         memcpy(&td->last_issue, &io_u->issue_time,
420                                         sizeof(io_u->issue_time));
421         }
422
423         return ret;
424 }
425
426 int td_io_init(struct thread_data *td)
427 {
428         int ret = 0;
429
430         if (td->io_ops->init) {
431                 ret = td->io_ops->init(td);
432                 if (ret)
433                         log_err("fio: io engine %s init failed.%s\n",
434                                 td->io_ops->name,
435                                 td->o.iodepth > 1 ?
436                                 " Perhaps try reducing io depth?" : "");
437                 else
438                         td->io_ops_init = 1;
439                 if (!td->error)
440                         td->error = ret;
441         }
442
443         return ret;
444 }
445
446 void td_io_commit(struct thread_data *td)
447 {
448         int ret;
449
450         dprint(FD_IO, "calling ->commit(), depth %d\n", td->cur_depth);
451
452         if (!td->cur_depth || !td->io_u_queued)
453                 return;
454
455         io_u_mark_depth(td, td->io_u_queued);
456
457         if (td->io_ops->commit) {
458                 ret = td->io_ops->commit(td);
459                 if (ret)
460                         td_verror(td, -ret, "io commit");
461         }
462
463         /*
464          * Reflect that events were submitted as async IO requests.
465          */
466         td->io_u_in_flight += td->io_u_queued;
467         td->io_u_queued = 0;
468 }
469
470 int td_io_open_file(struct thread_data *td, struct fio_file *f)
471 {
472         if (fio_file_closing(f)) {
473                 /*
474                  * Open translates to undo closing.
475                  */
476                 fio_file_clear_closing(f);
477                 get_file(f);
478                 return 0;
479         }
480         assert(!fio_file_open(f));
481         assert(f->fd == -1);
482         assert(td->io_ops->open_file);
483
484         if (td->io_ops->open_file(td, f)) {
485                 if (td->error == EINVAL && td->o.odirect)
486                         log_err("fio: destination does not support O_DIRECT\n");
487                 if (td->error == EMFILE) {
488                         log_err("fio: try reducing/setting openfiles (failed"
489                                 " at %u of %u)\n", td->nr_open_files,
490                                                         td->o.nr_files);
491                 }
492
493                 assert(f->fd == -1);
494                 assert(!fio_file_open(f));
495                 return 1;
496         }
497
498         fio_file_reset(td, f);
499         fio_file_set_open(f);
500         fio_file_clear_closing(f);
501         disk_util_inc(f->du);
502
503         td->nr_open_files++;
504         get_file(f);
505
506         if (f->filetype == FIO_TYPE_PIPE) {
507                 if (td_random(td)) {
508                         log_err("fio: can't seek on pipes (no random io)\n");
509                         goto err;
510                 }
511         }
512
513         if (td_ioengine_flagged(td, FIO_DISKLESSIO))
514                 goto done;
515
516         if (td->o.invalidate_cache && file_invalidate_cache(td, f))
517                 goto err;
518
519         if (td->o.fadvise_hint != F_ADV_NONE &&
520             (f->filetype == FIO_TYPE_BLOCK || f->filetype == FIO_TYPE_FILE)) {
521                 int flags;
522
523                 if (td->o.fadvise_hint == F_ADV_TYPE) {
524                         if (td_random(td))
525                                 flags = POSIX_FADV_RANDOM;
526                         else
527                                 flags = POSIX_FADV_SEQUENTIAL;
528                 } else if (td->o.fadvise_hint == F_ADV_RANDOM)
529                         flags = POSIX_FADV_RANDOM;
530                 else if (td->o.fadvise_hint == F_ADV_SEQUENTIAL)
531                         flags = POSIX_FADV_SEQUENTIAL;
532                 else {
533                         log_err("fio: unknown fadvise type %d\n",
534                                                         td->o.fadvise_hint);
535                         flags = POSIX_FADV_NORMAL;
536                 }
537
538                 if (posix_fadvise(f->fd, f->file_offset, f->io_size, flags) < 0) {
539                         if (!fio_did_warn(FIO_WARN_FADVISE))
540                                 log_err("fio: fadvise hint failed\n");
541                 }
542         }
543 #ifdef FIO_HAVE_WRITE_HINT
544         if (fio_option_is_set(&td->o, write_hint) &&
545             (f->filetype == FIO_TYPE_BLOCK || f->filetype == FIO_TYPE_FILE)) {
546                 uint64_t hint = td->o.write_hint;
547                 int cmd;
548
549                 /*
550                  * For direct IO, we just need/want to set the hint on
551                  * the file descriptor. For buffered IO, we need to set
552                  * it on the inode.
553                  */
554                 if (td->o.odirect)
555                         cmd = F_SET_FILE_RW_HINT;
556                 else
557                         cmd = F_SET_RW_HINT;
558
559                 if (fcntl(f->fd, cmd, &hint) < 0) {
560                         td_verror(td, errno, "fcntl write hint");
561                         goto err;
562                 }
563         }
564 #endif
565
566         if (td->o.odirect && !OS_O_DIRECT && fio_set_directio(td, f))
567                 goto err;
568
569 done:
570         log_file(td, f, FIO_LOG_OPEN_FILE);
571         return 0;
572 err:
573         disk_util_dec(f->du);
574         if (td->io_ops->close_file)
575                 td->io_ops->close_file(td, f);
576         return 1;
577 }
578
579 int td_io_close_file(struct thread_data *td, struct fio_file *f)
580 {
581         if (!fio_file_closing(f))
582                 log_file(td, f, FIO_LOG_CLOSE_FILE);
583
584         /*
585          * mark as closing, do real close when last io on it has completed
586          */
587         fio_file_set_closing(f);
588
589         return put_file(td, f);
590 }
591
592 int td_io_unlink_file(struct thread_data *td, struct fio_file *f)
593 {
594         if (td->io_ops->unlink_file)
595                 return td->io_ops->unlink_file(td, f);
596         else {
597                 int ret;
598
599                 ret = unlink(f->file_name);
600                 if (ret < 0)
601                         return errno;
602
603                 return 0;
604         }
605 }
606
607 int td_io_get_file_size(struct thread_data *td, struct fio_file *f)
608 {
609         if (!td->io_ops->get_file_size)
610                 return 0;
611
612         return td->io_ops->get_file_size(td, f);
613 }
614
615 int fio_show_ioengine_help(const char *engine)
616 {
617         struct flist_head *entry;
618         struct thread_data td;
619         struct ioengine_ops *io_ops;
620         char *sep;
621         int ret = 1;
622
623         if (!engine || !*engine) {
624                 log_info("Available IO engines:\n");
625                 flist_for_each(entry, &engine_list) {
626                         io_ops = flist_entry(entry, struct ioengine_ops, list);
627                         log_info("\t%s\n", io_ops->name);
628                 }
629                 return 0;
630         }
631         sep = strchr(engine, ',');
632         if (sep) {
633                 *sep = 0;
634                 sep++;
635         }
636
637         memset(&td, 0, sizeof(struct thread_data));
638         td.o.ioengine = (char *)engine;
639         io_ops = load_ioengine(&td);
640
641         if (!io_ops) {
642                 log_info("IO engine %s not found\n", engine);
643                 return 1;
644         }
645
646         if (io_ops->options)
647                 ret = show_cmd_help(io_ops->options, sep);
648         else
649                 log_info("IO engine %s has no options\n", io_ops->name);
650
651         free_ioengine(&td);
652         return ret;
653 }