diff --git a/HOWTO b/HOWTO index 8c9e41356b..4748743826 100644 --- a/HOWTO +++ b/HOWTO @@ -1944,6 +1944,7 @@ I/O engine **posixaio** POSIX asynchronous I/O using :manpage:`aio_read(3)` and :manpage:`aio_write(3)`. + This engine defines engine specific options. **solarisaio** Solaris native asynchronous I/O. @@ -2642,6 +2643,14 @@ with the caveat that when used on the command line, they must come after the If set, stdout and stderr streams are redirected to files named from the job name. Default is true. +.. options:: posixaio_respect_iodepth_batch_complete_max=bool : [posixaio] + + If set, limit batch completions according to + :option:`iodepth_batch_complete_max`, as other engines do. Default is + false, effectively behaving as though + :option:`iodepth_batch_complete_max` has the same value as + :option:`iodepth`. + I/O depth ~~~~~~~~~ diff --git a/engines/posixaio.c b/engines/posixaio.c index 135d088c7a..ec5d3c689b 100644 --- a/engines/posixaio.c +++ b/engines/posixaio.c @@ -11,12 +11,34 @@ #include #include "../fio.h" +#include "../optgroup.h" struct posixaio_data { struct io_u **aio_events; unsigned int queued; }; +struct posixaio_options { + void *pad; + unsigned int respect_iodepth_batch_complete_max; +}; + +static struct fio_option options[] = { + { + .name = "posixaio_respect_iodepth_batch_complete_max", + .lname = "Respect iodepth_batch_complete_max", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct posixaio_options, respect_iodepth_batch_complete_max), + .help = "Whether to cap batch completion", + .def = "0", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_POSIXAIO, + }, + { + .name = NULL, + }, +}; + static unsigned long long ts_utime_since_now(const struct timespec *start) { struct timespec now; @@ -61,6 +83,7 @@ static int fio_posixaio_getevents(struct thread_data *td, unsigned int min, unsigned int max, const struct timespec *t) { struct posixaio_data *pd = td->io_ops_data; + struct posixaio_options *o = td->eo; os_aiocb_t *suspend_list[SUSPEND_ENTRIES]; struct timespec start; int have_timeout = 0; @@ -105,6 +128,9 @@ static int fio_posixaio_getevents(struct thread_data *td, unsigned int min, io_u->resid = io_u->xfer_buflen - retval; } else io_u->error = err; + + if (o->respect_iodepth_batch_complete_max && r >= max) + break; } if (r >= min) @@ -221,6 +247,8 @@ static struct ioengine_ops ioengine = { .open_file = generic_open_file, .close_file = generic_close_file, .get_file_size = generic_get_file_size, + .options = options, + .option_struct_size = sizeof(struct posixaio_options), }; static void fio_init fio_posixaio_register(void) diff --git a/fio.1 b/fio.1 index a3ebb67d36..e182449a1f 100644 --- a/fio.1 +++ b/fio.1 @@ -2397,6 +2397,13 @@ Defines the time between the SIGTERM and SIGKILL signals. Default is 1 second. .TP .BI (exec)std_redirect\fR=\fbool If set, stdout and stderr streams are redirected to files named from the job name. Default is true. +.TP +.BI (posixaio)posixaio_respect_iodepth_batch_complete_max\fR=\fPbool +If set, limit batch completions according to +\fBiodepth_batch_complete_max\fR, as other engines do. Default is +false, effectively setting +\fBiodepth_batch_complete_max\fR to the same value as +\fBiodepth\fR. .SS "I/O depth" .TP .BI iodepth \fR=\fPint diff --git a/optgroup.h b/optgroup.h index 1fb84a296b..af6bf81e1c 100644 --- a/optgroup.h +++ b/optgroup.h @@ -71,6 +71,7 @@ enum opt_category_group { __FIO_OPT_G_LIBCUFILE, __FIO_OPT_G_DFS, __FIO_OPT_G_NFS, + __FIO_OPT_G_POSIXAIO, FIO_OPT_G_RATE = (1ULL << __FIO_OPT_G_RATE), FIO_OPT_G_ZONE = (1ULL << __FIO_OPT_G_ZONE), @@ -116,6 +117,7 @@ enum opt_category_group { FIO_OPT_G_FILESTAT = (1ULL << __FIO_OPT_G_FILESTAT), FIO_OPT_G_LIBCUFILE = (1ULL << __FIO_OPT_G_LIBCUFILE), FIO_OPT_G_DFS = (1ULL << __FIO_OPT_G_DFS), + FIO_OPT_G_POSIXAIO = (1ULL << __FIO_OPT_G_POSIXAIO), }; extern const struct opt_group *opt_group_from_mask(uint64_t *mask);