Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 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 <stdio.h> |
| 13 | #include <stdlib.h> |
| 14 | #include <unistd.h> |
Jens Axboe | 5c4e1db | 2006-06-07 14:17:08 +0200 | [diff] [blame] | 15 | #include <string.h> |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 16 | #include <dlfcn.h> |
Jens Axboe | 8c16d84 | 2006-10-20 11:48:33 +0200 | [diff] [blame] | 17 | |
Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 18 | #include "fio.h" |
| 19 | #include "os.h" |
| 20 | |
Jens Axboe | 8c16d84 | 2006-10-20 11:48:33 +0200 | [diff] [blame] | 21 | static int check_engine_ops(struct ioengine_ops *ops) |
| 22 | { |
| 23 | /* |
| 24 | * cpu thread doesn't need to provide anything |
| 25 | */ |
| 26 | if (ops->flags & FIO_CPUIO) |
| 27 | return 0; |
| 28 | |
| 29 | if (!ops->event) { |
| 30 | log_err("%s: no event handler)\n", ops->name); |
| 31 | return 1; |
| 32 | } |
| 33 | if (!ops->getevents) { |
| 34 | log_err("%s: no getevents handler)\n", ops->name); |
| 35 | return 1; |
| 36 | } |
| 37 | if (!ops->queue) { |
| 38 | log_err("%s: no queue handler)\n", ops->name); |
| 39 | return 1; |
| 40 | } |
| 41 | |
| 42 | return 0; |
| 43 | } |
| 44 | |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 45 | struct ioengine_ops *load_ioengine(struct thread_data *td, char *name) |
Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 46 | { |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 47 | char engine[16], engine_lib[256]; |
Jens Axboe | 8458500 | 2006-10-19 20:26:22 +0200 | [diff] [blame] | 48 | struct ioengine_ops *ops, *ret; |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 49 | void *dlhandle; |
Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 50 | |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 51 | strcpy(engine, name); |
Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 52 | |
| 53 | /* |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 54 | * linux libaio has alias names, so convert to what we want |
Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 55 | */ |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 56 | if (!strncmp(engine, "linuxaio", 8) || !strncmp(engine, "aio", 3)) |
| 57 | strcpy(engine, "libaio"); |
| 58 | |
Jens Axboe | c1d5725 | 2006-10-09 19:56:04 +0200 | [diff] [blame] | 59 | sprintf(engine_lib, "%s/lib/fio/fio-engine-%s.o", fio_inst_prefix, engine); |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 60 | dlerror(); |
| 61 | dlhandle = dlopen(engine_lib, RTLD_LAZY); |
Jens Axboe | d4dbaaa | 2006-10-09 16:01:27 +0200 | [diff] [blame] | 62 | if (!dlhandle) { |
| 63 | td_vmsg(td, -1, dlerror()); |
| 64 | return NULL; |
| 65 | } |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 66 | |
| 67 | ops = dlsym(dlhandle, "ioengine"); |
Jens Axboe | d4dbaaa | 2006-10-09 16:01:27 +0200 | [diff] [blame] | 68 | if (!ops) { |
| 69 | td_vmsg(td, -1, dlerror()); |
| 70 | dlclose(dlhandle); |
| 71 | return NULL; |
| 72 | } |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 73 | |
Jens Axboe | b902ceb | 2006-10-09 16:11:45 +0200 | [diff] [blame] | 74 | if (ops->version != FIO_IOOPS_VERSION) { |
| 75 | log_err("bad ioops version %d (want %d)\n", ops->version, FIO_IOOPS_VERSION); |
| 76 | dlclose(dlhandle); |
| 77 | return NULL; |
| 78 | } |
| 79 | |
Jens Axboe | 8c16d84 | 2006-10-20 11:48:33 +0200 | [diff] [blame] | 80 | /* |
| 81 | * Check that the required methods are there. |
| 82 | */ |
| 83 | if (check_engine_ops(ops)) { |
| 84 | dlclose(dlhandle); |
| 85 | return NULL; |
| 86 | } |
| 87 | |
Jens Axboe | 8458500 | 2006-10-19 20:26:22 +0200 | [diff] [blame] | 88 | ret = malloc(sizeof(*ret)); |
| 89 | memcpy(ret, ops, sizeof(*ret)); |
| 90 | ret->data = NULL; |
| 91 | ret->dlhandle = dlhandle; |
| 92 | |
| 93 | return ret; |
Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 94 | } |
| 95 | |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 96 | void close_ioengine(struct thread_data *td) |
Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 97 | { |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 98 | if (td->io_ops->cleanup) |
| 99 | td->io_ops->cleanup(td); |
Jens Axboe | ebac465 | 2005-12-08 15:25:21 +0100 | [diff] [blame] | 100 | |
Jens Axboe | 2866c82 | 2006-10-09 15:57:48 +0200 | [diff] [blame] | 101 | dlclose(td->io_ops->dlhandle); |
Jens Axboe | 8458500 | 2006-10-19 20:26:22 +0200 | [diff] [blame] | 102 | free(td->io_ops); |
| 103 | td->io_ops = NULL; |
Jens Axboe | b990b5c | 2006-09-14 09:48:22 +0200 | [diff] [blame] | 104 | } |
Jens Axboe | 10ba535 | 2006-10-20 11:39:27 +0200 | [diff] [blame] | 105 | |
| 106 | int td_io_prep(struct thread_data *td, struct io_u *io_u) |
| 107 | { |
| 108 | if (td->io_ops->prep && td->io_ops->prep(td, io_u)) |
| 109 | return 1; |
| 110 | |
| 111 | return 0; |
| 112 | } |
| 113 | |
Jens Axboe | 10ba535 | 2006-10-20 11:39:27 +0200 | [diff] [blame] | 114 | int td_io_getevents(struct thread_data *td, int min, int max, |
| 115 | struct timespec *t) |
| 116 | { |
| 117 | return td->io_ops->getevents(td, min, max, t); |
| 118 | } |
| 119 | |
| 120 | int td_io_queue(struct thread_data *td, struct io_u *io_u) |
| 121 | { |
| 122 | gettimeofday(&io_u->issue_time, NULL); |
| 123 | |
| 124 | return td->io_ops->queue(td, io_u); |
| 125 | } |
Jens Axboe | 8c16d84 | 2006-10-20 11:48:33 +0200 | [diff] [blame] | 126 | |
| 127 | int td_io_init(struct thread_data *td) |
| 128 | { |
| 129 | if (td->io_ops->init) |
| 130 | return td->io_ops->init(td); |
| 131 | |
| 132 | return 0; |
| 133 | } |