solarisaio.c revision 0f09e829c3e1aa24d16059ab6665098fedf17c05
1/* 2 * Native Solaris async IO engine 3 * 4 */ 5#include <stdio.h> 6#include <stdlib.h> 7#include <unistd.h> 8#include <errno.h> 9 10#include "../fio.h" 11 12#ifdef FIO_HAVE_SOLARISAIO 13 14#include <sys/asynch.h> 15 16struct solarisaio_data { 17 struct io_u **aio_events; 18 unsigned int nr; 19 unsigned int max_depth; 20}; 21 22static int fio_solarisaio_cancel(struct thread_data fio_unused *td, 23 struct io_u *io_u) 24{ 25 return aiocancel(&io_u->resultp); 26} 27 28static int fio_solarisaio_prep(struct thread_data fio_unused *td, 29 struct io_u *io_u) 30{ 31 io_u->resultp.aio_return = AIO_INPROGRESS; 32 return 0; 33} 34 35static int fio_solarisaio_getevents(struct thread_data *td, unsigned int min, 36 unsigned int max, struct timespec *t) 37{ 38 struct solarisaio_data *sd = td->io_ops->data; 39 struct timeval tv; 40 unsigned int r; 41 42 r = 0; 43 do { 44 struct io_u *io_u; 45 aio_result_t *p; 46 47 if (!min || !t) { 48 tv.tv_sec = 0; 49 tv.tv_usec = 0; 50 } else { 51 tv.tv_sec = t->tv_sec; 52 tv.tv_usec = t->tv_nsec / 1000; 53 } 54 55 p = aiowait(&tv); 56 if (p == (aio_result_t *) -1) { 57 int err = errno; 58 59 if (err == EINVAL) 60 break; 61 td_verror(td, err, "aiowait"); 62 break; 63 } else if (p != NULL) { 64 io_u = container_of(p, struct io_u, resultp); 65 66 sd->aio_events[r++] = io_u; 67 sd->nr--; 68 69 if (io_u->resultp.aio_return >= 0) { 70 io_u->resid = io_u->xfer_buflen 71 - io_u->resultp.aio_return; 72 io_u->error = 0; 73 } else 74 io_u->error = io_u->resultp.aio_return; 75 } 76 } while (r < min); 77 78 return r; 79} 80 81static struct io_u *fio_solarisaio_event(struct thread_data *td, int event) 82{ 83 struct solarisaio_data *sd = td->io_ops->data; 84 85 return sd->aio_events[event]; 86} 87 88static int fio_solarisaio_queue(struct thread_data fio_unused *td, 89 struct io_u *io_u) 90{ 91 struct solarisaio_data *sd = td->io_ops->data; 92 struct fio_file *f = io_u->file; 93 off_t off; 94 int ret; 95 96 fio_ro_check(td, io_u); 97 98 if (io_u->ddir == DDIR_SYNC) { 99 if (sd->nr) 100 return FIO_Q_BUSY; 101 if (fsync(f->fd) < 0) 102 io_u->error = errno; 103 104 return FIO_Q_COMPLETED; 105 } 106 107 if (sd->nr == sd->max_depth) 108 return FIO_Q_BUSY; 109 110 off = io_u->offset; 111 if (io_u->ddir == DDIR_READ) 112 ret = aioread(f->fd, io_u->xfer_buf, io_u->xfer_buflen, off, 113 SEEK_SET, &io_u->resultp); 114 else 115 ret = aiowrite(f->fd, io_u->xfer_buf, io_u->xfer_buflen, off, 116 SEEK_SET, &io_u->resultp); 117 if (ret) { 118 io_u->error = errno; 119 td_verror(td, io_u->error, "xfer"); 120 return FIO_Q_COMPLETED; 121 } 122 123 sd->nr++; 124 return FIO_Q_QUEUED; 125} 126 127static void fio_solarisaio_cleanup(struct thread_data *td) 128{ 129 struct solarisaio_data *sd = td->io_ops->data; 130 131 if (sd) { 132 free(sd->aio_events); 133 free(sd); 134 } 135} 136 137static int fio_solarisaio_init(struct thread_data *td) 138{ 139 struct solarisaio_data *sd = malloc(sizeof(*sd)); 140 unsigned int max_depth; 141 142 max_depth = td->o.iodepth; 143 if (max_depth > MAXASYNCHIO) { 144 max_depth = MAXASYNCHIO; 145 log_info("fio: lower depth to %d due to OS constraints\n", 146 max_depth); 147 } 148 149 memset(sd, 0, sizeof(*sd)); 150 sd->aio_events = malloc(max_depth * sizeof(struct io_u *)); 151 memset(sd->aio_events, 0, max_depth * sizeof(struct io_u *)); 152 sd->max_depth = max_depth; 153 154 td->io_ops->data = sd; 155 return 0; 156} 157 158static struct ioengine_ops ioengine = { 159 .name = "solarisaio", 160 .version = FIO_IOOPS_VERSION, 161 .init = fio_solarisaio_init, 162 .prep = fio_solarisaio_prep, 163 .queue = fio_solarisaio_queue, 164 .cancel = fio_solarisaio_cancel, 165 .getevents = fio_solarisaio_getevents, 166 .event = fio_solarisaio_event, 167 .cleanup = fio_solarisaio_cleanup, 168 .open_file = generic_open_file, 169 .close_file = generic_close_file, 170}; 171 172#else /* FIO_HAVE_SOLARISAIO */ 173 174/* 175 * When we have a proper configure system in place, we simply wont build 176 * and install this io engine. For now install a crippled version that 177 * just complains and fails to load. 178 */ 179static int fio_solarisaio_init(struct thread_data fio_unused *td) 180{ 181 fprintf(stderr, "fio: solarisaio not available\n"); 182 return 1; 183} 184 185static struct ioengine_ops ioengine = { 186 .name = "solarisaio", 187 .version = FIO_IOOPS_VERSION, 188 .init = fio_solarisaio_init, 189}; 190 191#endif 192 193static void fio_init fio_solarisaio_register(void) 194{ 195 register_ioengine(&ioengine); 196} 197 198static void fio_exit fio_solarisaio_unregister(void) 199{ 200 unregister_ioengine(&ioengine); 201} 202