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