diff --git a/HOWTO b/HOWTO index df931e592b..a4eadc1703 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. **posixaio_waitcomplete** POSIX asynchronous I/O, using FreeBSD's @@ -2609,6 +2610,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 078d80e14a..a14324e580 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; @@ -114,6 +136,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; @@ -158,6 +181,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) @@ -274,6 +300,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), }; #ifdef CONFIG_HAVE_AIO_WAITCOMPLETE diff --git a/fio.1 b/fio.1 index 1f69dd710c..1ebe694101 100644 --- a/fio.1 +++ b/fio.1 @@ -2372,6 +2372,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=\fbool +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);