ioengines.c revision 8c16d840377c1e6fb79f479ee60590a2da5b52ee
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> 15#include <string.h> 16#include <dlfcn.h> 17 18#include "fio.h" 19#include "os.h" 20 21static 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 45struct ioengine_ops *load_ioengine(struct thread_data *td, char *name) 46{ 47 char engine[16], engine_lib[256]; 48 struct ioengine_ops *ops, *ret; 49 void *dlhandle; 50 51 strcpy(engine, name); 52 53 /* 54 * linux libaio has alias names, so convert to what we want 55 */ 56 if (!strncmp(engine, "linuxaio", 8) || !strncmp(engine, "aio", 3)) 57 strcpy(engine, "libaio"); 58 59 sprintf(engine_lib, "%s/lib/fio/fio-engine-%s.o", fio_inst_prefix, engine); 60 dlerror(); 61 dlhandle = dlopen(engine_lib, RTLD_LAZY); 62 if (!dlhandle) { 63 td_vmsg(td, -1, dlerror()); 64 return NULL; 65 } 66 67 ops = dlsym(dlhandle, "ioengine"); 68 if (!ops) { 69 td_vmsg(td, -1, dlerror()); 70 dlclose(dlhandle); 71 return NULL; 72 } 73 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 80 /* 81 * Check that the required methods are there. 82 */ 83 if (check_engine_ops(ops)) { 84 dlclose(dlhandle); 85 return NULL; 86 } 87 88 ret = malloc(sizeof(*ret)); 89 memcpy(ret, ops, sizeof(*ret)); 90 ret->data = NULL; 91 ret->dlhandle = dlhandle; 92 93 return ret; 94} 95 96void close_ioengine(struct thread_data *td) 97{ 98 if (td->io_ops->cleanup) 99 td->io_ops->cleanup(td); 100 101 dlclose(td->io_ops->dlhandle); 102 free(td->io_ops); 103 td->io_ops = NULL; 104} 105 106int 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 114int td_io_sync(struct thread_data *td, struct fio_file *f) 115{ 116 if (td->io_ops->sync) 117 return td->io_ops->sync(td, f); 118 119 return 0; 120} 121 122int td_io_getevents(struct thread_data *td, int min, int max, 123 struct timespec *t) 124{ 125 return td->io_ops->getevents(td, min, max, t); 126} 127 128int td_io_queue(struct thread_data *td, struct io_u *io_u) 129{ 130 gettimeofday(&io_u->issue_time, NULL); 131 132 return td->io_ops->queue(td, io_u); 133} 134 135int td_io_init(struct thread_data *td) 136{ 137 if (td->io_ops->init) 138 return td->io_ops->init(td); 139 140 return 0; 141} 142