From: Jens Axboe Date: Mon, 2 Jun 2008 09:59:30 +0000 (+0200) Subject: Add Solaris native aio engine X-Git-Tag: fio-1.21-rc5~10 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=417f006858ec66f0b410c83c2e13da54662048e0 Add Solaris native aio engine Signed-off-by: Jens Axboe --- diff --git a/HOWTO b/HOWTO index 15ee367b..12974f3f 100644 --- a/HOWTO +++ b/HOWTO @@ -375,6 +375,8 @@ ioengine=str Defines how the job issues io to the file. The following posixaio glibc posix asynchronous io. + solarisaio Solaris native asynchronous io. + mmap File is memory mapped and data copied to/from using memcpy(3). diff --git a/Makefile.solaris b/Makefile.solaris index f92a92e4..f7235dbb 100644 --- a/Makefile.solaris +++ b/Makefile.solaris @@ -20,6 +20,7 @@ OBJS += engines/posixaio.o OBJS += engines/sync.o OBJS += engines/null.o OBJS += engines/net.o +OBJS += engines/solarisaio.o INSTALL = install prefix = /usr/local diff --git a/engines/solarisaio.c b/engines/solarisaio.c new file mode 100644 index 00000000..ab27b55d --- /dev/null +++ b/engines/solarisaio.c @@ -0,0 +1,184 @@ +/* + * Native Solaris async IO engine + * + */ +#include +#include +#include +#include + +#include "../fio.h" + +#ifdef FIO_HAVE_SOLARISAIO + +#include + +struct solarisaio_data { + struct io_u **aio_events; + unsigned int nr; +}; + +static int fio_solarisaio_cancel(struct thread_data fio_unused *td, + struct io_u *io_u) +{ + return aiocancel(&io_u->resultp); +} + +static int fio_solarisaio_prep(struct thread_data fio_unused *td, + struct io_u *io_u) +{ + io_u->resultp.aio_return = AIO_INPROGRESS; + return 0; +} + +static int fio_solarisaio_getevents(struct thread_data *td, unsigned int min, + unsigned int max, struct timespec *t) +{ + struct solarisaio_data *sd = td->io_ops->data; + struct timeval tv; + unsigned int r; + + r = 0; + do { + struct io_u *io_u; + aio_result_t *p; + + if (!min || !t) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = t->tv_sec; + tv.tv_usec = t->tv_nsec / 1000; + } + + p = aiowait(&tv); + if (p) { + io_u = container_of(p, struct io_u, resultp); + + sd->aio_events[r++] = io_u; + sd->nr--; + + if (io_u->resultp.aio_return >= 0) { + io_u->resid = io_u->xfer_buflen + - io_u->resultp.aio_return; + io_u->error = 0; + } else + io_u->error = io_u->resultp.aio_return; + } + } while (r < min); + + return r; +} + +static struct io_u *fio_solarisaio_event(struct thread_data *td, int event) +{ + struct solarisaio_data *sd = td->io_ops->data; + + return sd->aio_events[event]; +} + +static int fio_solarisaio_queue(struct thread_data fio_unused *td, + struct io_u *io_u) +{ + struct solarisaio_data *sd = td->io_ops->data; + struct fio_file *f = io_u->file; + off_t off; + int ret; + + fio_ro_check(td, io_u); + + if (io_u->ddir == DDIR_SYNC) { + if (sd->nr) + return FIO_Q_BUSY; + if (fsync(f->fd) < 0) + io_u->error = errno; + + return FIO_Q_COMPLETED; + } + + if (sd->nr == td->o.iodepth) + return FIO_Q_BUSY; + + off = io_u->offset; + if (io_u->ddir == DDIR_READ) + ret = aioread(f->fd, io_u->xfer_buf, io_u->xfer_buflen, off, + SEEK_SET, &io_u->resultp); + else + ret = aiowrite(f->fd, io_u->xfer_buf, io_u->xfer_buflen, off, + SEEK_SET, &io_u->resultp); + if (ret) { + io_u->error = errno; + td_verror(td, io_u->error, "xfer"); + return FIO_Q_COMPLETED; + } + + sd->nr++; + return FIO_Q_QUEUED; +} + +static void fio_solarisaio_cleanup(struct thread_data *td) +{ + struct solarisaio_data *sd = td->io_ops->data; + + if (sd) { + free(sd->aio_events); + free(sd); + } +} + +static int fio_solarisaio_init(struct thread_data *td) +{ + struct solarisaio_data *sd = malloc(sizeof(*sd)); + + memset(sd, 0, sizeof(*sd)); + sd->aio_events = malloc(td->o.iodepth * sizeof(struct io_u *)); + memset(sd->aio_events, 0, td->o.iodepth * sizeof(struct io_u *)); + + td->io_ops->data = sd; + return 0; +} + +static struct ioengine_ops ioengine = { + .name = "solarisaio", + .version = FIO_IOOPS_VERSION, + .init = fio_solarisaio_init, + .prep = fio_solarisaio_prep, + .queue = fio_solarisaio_queue, + .cancel = fio_solarisaio_cancel, + .getevents = fio_solarisaio_getevents, + .event = fio_solarisaio_event, + .cleanup = fio_solarisaio_cleanup, + .open_file = generic_open_file, + .close_file = generic_close_file, +}; + +#else /* FIO_HAVE_SOLARISAIO */ + +/* + * When we have a proper configure system in place, we simply wont build + * and install this io engine. For now install a crippled version that + * just complains and fails to load. + */ +static int fio_solarisaio_init(struct thread_data fio_unused *td) +{ + fprintf(stderr, "fio: solarisaio not available\n"); + return 1; +} + +static struct ioengine_ops ioengine = { + .name = "solarisaio", + .version = FIO_IOOPS_VERSION, + .init = fio_solarisaio_init, +}; + +#endif + +static void fio_init fio_solarisaio_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_solarisaio_unregister(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/fio.h b/fio.h index a1555181..b1792abe 100644 --- a/fio.h +++ b/fio.h @@ -29,6 +29,10 @@ #include #endif +#ifdef FIO_HAVE_SOLARISAIO +#include +#endif + enum fio_ddir { DDIR_READ = 0, DDIR_WRITE, @@ -126,6 +130,9 @@ struct io_u { #endif #ifdef FIO_HAVE_GUASI guasi_req_t greq; +#endif +#ifdef FIO_HAVE_SOLARISAIO + aio_result_t resultp; #endif }; struct timeval start_time; diff --git a/options.c b/options.c index 5aad0050..cc131a28 100644 --- a/options.c +++ b/options.c @@ -556,6 +556,11 @@ static struct fio_option options[] = { { .ival = "posixaio", .help = "POSIX asynchronous IO", }, +#endif +#ifdef FIO_HAVE_SOLARISAIO + { .ival = "solarisaio", + .help = "Solaris native asynchronous IO", + }, #endif { .ival = "mmap", .help = "Memory mapped IO", diff --git a/os/os-solaris.h b/os/os-solaris.h index 21d28e98..7fa0bb50 100644 --- a/os/os-solaris.h +++ b/os/os-solaris.h @@ -3,6 +3,7 @@ #undef FIO_HAVE_LIBAIO #define FIO_HAVE_POSIXAIO +#define FIO_HAVE_SOLARISAIO #undef FIO_HAVE_FADVISE #undef FIO_HAVE_CPU_AFFINITY #undef FIO_HAVE_DISK_UTIL