X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fsolarisaio.c;h=069cda5347c903d9f458772508b2f6eed0d2fc39;hp=f7f832b8b9ae66842011274f6053ac82ab0f9dde;hb=a1c58075279454a91ec43366846b93e8dcf9753c;hpb=0f09e829c3e1aa24d16059ab6665098fedf17c05 diff --git a/engines/solarisaio.c b/engines/solarisaio.c index f7f832b8..069cda53 100644 --- a/engines/solarisaio.c +++ b/engines/solarisaio.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "../fio.h" @@ -15,6 +16,7 @@ struct solarisaio_data { struct io_u **aio_events; + unsigned int aio_pending; unsigned int nr; unsigned int max_depth; }; @@ -28,54 +30,74 @@ static int fio_solarisaio_cancel(struct thread_data fio_unused *td, static int fio_solarisaio_prep(struct thread_data fio_unused *td, struct io_u *io_u) { + struct solarisaio_data *sd = td->io_ops->data; + io_u->resultp.aio_return = AIO_INPROGRESS; + io_u->engine_data = sd; return 0; } +static void wait_for_event(struct timeval *tv) +{ + struct solarisaio_data *sd; + struct io_u *io_u; + aio_result_t *res; + + res = aiowait(tv); + if (res == (aio_result_t *) -1) { + int err = errno; + + if (err != EINVAL) { + log_err("fio: solarisaio got %d in aiowait\n", err); + exit(err); + } + return; + } else if (!res) + return; + + io_u = container_of(res, struct io_u, resultp); + sd = io_u->engine_data; + + 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_errno; + + /* + * For SIGIO, we need a write barrier between the two, so that + * the ->aio_pending store is seen after the ->aio_events store + */ + sd->aio_events[sd->aio_pending] = io_u; + write_barrier(); + sd->aio_pending++; + sd->nr--; +} + 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; - } + int ret; - p = aiowait(&tv); - if (p == (aio_result_t *) -1) { - int err = errno; - - if (err == EINVAL) - break; - td_verror(td, err, "aiowait"); - break; - } else if (p != NULL) { - 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); + 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; + } - return r; + while (sd->aio_pending < min) + wait_for_event(&tv); + + /* + * should be OK without locking, as int operations should be atomic + */ + ret = sd->aio_pending; + sd->aio_pending -= ret; + return ret; } static struct io_u *fio_solarisaio_event(struct thread_data *td, int event) @@ -104,6 +126,15 @@ static int fio_solarisaio_queue(struct thread_data fio_unused *td, return FIO_Q_COMPLETED; } + if (io_u->ddir == DDIR_DATASYNC) { + if (sd->nr) + return FIO_Q_BUSY; + if (fdatasync(f->fd) < 0) + io_u->error = errno; + + return FIO_Q_COMPLETED; + } + if (sd->nr == sd->max_depth) return FIO_Q_BUSY; @@ -134,6 +165,26 @@ static void fio_solarisaio_cleanup(struct thread_data *td) } } +/* + * Set USE_SIGNAL_COMPLETIONS to use SIGIO as completion events. + */ +#ifdef USE_SIGNAL_COMPLETIONS +static void fio_solarisaio_sigio(int sig) +{ + wait_for_event(NULL); +} + +static void fio_solarisaio_init_sigio(void) +{ + struct sigaction act; + + memset(&act, 0, sizeof(act)); + act.sa_handler = fio_solarisaio_sigio; + act.sa_flags = SA_RESTART; + sigaction(SIGIO, &act, NULL); +} +#endif + static int fio_solarisaio_init(struct thread_data *td) { struct solarisaio_data *sd = malloc(sizeof(*sd)); @@ -151,6 +202,10 @@ static int fio_solarisaio_init(struct thread_data *td) memset(sd->aio_events, 0, max_depth * sizeof(struct io_u *)); sd->max_depth = max_depth; +#ifdef USE_SIGNAL_COMPLETIONS + fio_solarisaio_init_sigio(); +#endif + td->io_ops->data = sd; return 0; } @@ -167,6 +222,7 @@ static struct ioengine_ops ioengine = { .cleanup = fio_solarisaio_cleanup, .open_file = generic_open_file, .close_file = generic_close_file, + .get_file_size = generic_get_file_size, }; #else /* FIO_HAVE_SOLARISAIO */