X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fsolarisaio.c;h=dfaa375a1e0aa6a06c91d97a6e54d93d9fb87041;hp=ab27b55d32f96380e120cc5aff46ba8d4628746e;hb=44c47feb9edc7854bf3cfa2e3d843e90fc969b3a;hpb=417f006858ec66f0b410c83c2e13da54662048e0 diff --git a/engines/solarisaio.c b/engines/solarisaio.c index ab27b55d..dfaa375a 100644 --- a/engines/solarisaio.c +++ b/engines/solarisaio.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "../fio.h" @@ -15,7 +16,9 @@ struct solarisaio_data { struct io_u **aio_events; + unsigned int aio_pending; unsigned int nr; + unsigned int max_depth; }; static int fio_solarisaio_cancel(struct thread_data fio_unused *td, @@ -27,47 +30,79 @@ 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_return; + + /* + * 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 void fio_solarisaio_sigio(int sig) +{ + wait_for_event(NULL); +} + 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); + int ret; - sd->aio_events[r++] = io_u; - sd->nr--; + 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; + } - 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); + while (sd->aio_pending < min) + wait_for_event(&tv); - return r; + /* + * 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) @@ -96,7 +131,7 @@ static int fio_solarisaio_queue(struct thread_data fio_unused *td, return FIO_Q_COMPLETED; } - if (sd->nr == td->o.iodepth) + if (sd->nr == sd->max_depth) return FIO_Q_BUSY; off = io_u->offset; @@ -126,13 +161,39 @@ static void fio_solarisaio_cleanup(struct thread_data *td) } } +/* + * Set USE_SIGNAL_COMPLETIONS to use SIGIO as completion events. + */ +static void fio_solarisaio_init_sigio(void) +{ +#ifdef USE_SIGNAL_COMPLETIONS + 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)); + unsigned int max_depth; + + max_depth = td->o.iodepth; + if (max_depth > MAXASYNCHIO) { + max_depth = MAXASYNCHIO; + log_info("fio: lower depth to %d due to OS constraints\n", + max_depth); + } 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 *)); + sd->aio_events = malloc(max_depth * sizeof(struct io_u *)); + memset(sd->aio_events, 0, max_depth * sizeof(struct io_u *)); + sd->max_depth = max_depth; + + fio_solarisaio_init_sigio(); td->io_ops->data = sd; return 0;