Skip to content

Commit

Permalink
cmdprio: Add support for per I/O priority hint
Browse files Browse the repository at this point in the history
Introduce the new option cmdprio_hint to allow specifying I/O priority
hints per IO with the io_uring and libaio IO engines. A third acceptable
format for the cmdprio_bssplit option is also introduced to allow
specifying an I/O hint in addition to a priority class and level.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
Link: https://lore.kernel.org/r/20230721110510.44772-6-dlemoal@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
damien-lemoal authored and axboe committed Jul 21, 2023
1 parent 860462d commit 79012fe
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 16 deletions.
28 changes: 24 additions & 4 deletions HOWTO.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2287,6 +2287,16 @@ with the caveat that when used on the command line, they must come after the
reads and writes. See :manpage:`ionice(1)`. See also the
:option:`prioclass` option.

.. option:: cmdprio_hint=int[,int] : [io_uring] [libaio]

Set the I/O priority hint to use for I/Os that must be issued with
a priority when :option:`cmdprio_percentage` or
:option:`cmdprio_bssplit` is set. If not specified when
:option:`cmdprio_percentage` or :option:`cmdprio_bssplit` is set,
this defaults to 0 (no hint). A single value applies to reads and
writes. Comma-separated values may be specified for reads and writes.
See also the :option:`priohint` option.

.. option:: cmdprio=int[,int] : [io_uring] [libaio]

Set the I/O priority value to use for I/Os that must be issued with
Expand All @@ -2313,9 +2323,9 @@ with the caveat that when used on the command line, they must come after the

cmdprio_bssplit=blocksize/percentage:blocksize/percentage

In this case, each entry will use the priority class and priority
level defined by the options :option:`cmdprio_class` and
:option:`cmdprio` respectively.
In this case, each entry will use the priority class, priority hint
and priority level defined by the options :option:`cmdprio_class`,
:option:`cmdprio` and :option:`cmdprio_hint` respectively.

The second accepted format for this option is:

Expand All @@ -2326,7 +2336,14 @@ with the caveat that when used on the command line, they must come after the
accepted format does not restrict all entries to have the same priority
class and priority level.

For both formats, only the read and write data directions are supported,
The third accepted format for this option is:

cmdprio_bssplit=blocksize/percentage/class/level/hint:...

This is an extension of the second accepted format that allows to also
specify a priority hint.

For all formats, only the read and write data directions are supported,
values for trim IOs are ignored. This option is mutually exclusive with
the :option:`cmdprio_percentage` option.

Expand Down Expand Up @@ -3445,6 +3462,9 @@ Threads, processes and job synchronization
of I/Os so that the device can optimize its internal command scheduling
according to the latency limits indicated by the user.

For per-I/O priority hint setting, see the I/O engine specific
:option:`cmdprio_hint` option.

.. option:: cpus_allowed=str

Controls the same options as :option:`cpumask`, but accepts a textual
Expand Down
9 changes: 6 additions & 3 deletions engines/cmdprio.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ static int fio_cmdprio_percentage(struct cmdprio *cmdprio, struct io_u *io_u,
* to be set. If the random percentage value is within the user specified
* percentage of I/Os that should use a cmdprio priority value (rather than
* the default priority), then this function updates the io_u with an ioprio
* value as defined by the cmdprio/cmdprio_class or cmdprio_bssplit options.
* value as defined by the cmdprio/cmdprio_hint/cmdprio_class or
* cmdprio_bssplit options.
*
* Return true if the io_u ioprio was changed and false otherwise.
*/
Expand Down Expand Up @@ -342,7 +343,8 @@ static int fio_cmdprio_gen_perc(struct thread_data *td, struct cmdprio *cmdprio)
prio = &cmdprio->perc_entry[ddir];
prio->perc = options->percentage[ddir];
prio->prio = ioprio_value(options->class[ddir],
options->level[ddir], 0);
options->level[ddir],
options->hint[ddir]);
assign_clat_prio_index(prio, &values[ddir]);

ret = init_ts_clat_prio(ts, ddir, &values[ddir]);
Expand Down Expand Up @@ -400,7 +402,8 @@ static int fio_cmdprio_parse_and_gen_bssplit(struct thread_data *td,
goto err;

implicit_cmdprio = ioprio_value(options->class[ddir],
options->level[ddir], 0);
options->level[ddir],
options->hint[ddir]);

ret = fio_cmdprio_generate_bsprio_desc(&cmdprio->bsprio_desc[ddir],
&parse_res[ddir],
Expand Down
22 changes: 22 additions & 0 deletions engines/cmdprio.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct cmdprio_options {
unsigned int percentage[CMDPRIO_RWDIR_CNT];
unsigned int class[CMDPRIO_RWDIR_CNT];
unsigned int level[CMDPRIO_RWDIR_CNT];
unsigned int hint[CMDPRIO_RWDIR_CNT];
char *bssplit_str;
};

Expand Down Expand Up @@ -74,6 +75,21 @@ struct cmdprio_options {
.category = FIO_OPT_C_ENGINE, \
.group = opt_group, \
}, \
{ \
.name = "cmdprio_hint", \
.lname = "Asynchronous I/O priority hint", \
.type = FIO_OPT_INT, \
.off1 = offsetof(opt_struct, \
cmdprio_options.hint[DDIR_READ]), \
.off2 = offsetof(opt_struct, \
cmdprio_options.hint[DDIR_WRITE]), \
.help = "Set asynchronous IO priority hint", \
.minval = IOPRIO_MIN_PRIO_HINT, \
.maxval = IOPRIO_MAX_PRIO_HINT, \
.interval = 1, \
.category = FIO_OPT_C_ENGINE, \
.group = opt_group, \
}, \
{ \
.name = "cmdprio", \
.lname = "Asynchronous I/O priority level", \
Expand Down Expand Up @@ -112,6 +128,12 @@ struct cmdprio_options {
.type = FIO_OPT_UNSUPPORTED, \
.help = "Platform does not support I/O priority classes", \
}, \
{ \
.name = "cmdprio_hint", \
.lname = "Asynchronous I/O priority hint", \
.type = FIO_OPT_UNSUPPORTED, \
.help = "Platform does not support I/O priority classes", \
}, \
{ \
.name = "cmdprio", \
.lname = "Asynchronous I/O priority level", \
Expand Down
4 changes: 2 additions & 2 deletions engines/io_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ static int fio_ioring_prep(struct thread_data *td, struct io_u *io_u)
/*
* Since io_uring can have a submission context (sqthread_poll)
* that is different from the process context, we cannot rely on
* the IO priority set by ioprio_set() (option prio/prioclass)
* to be inherited.
* the IO priority set by ioprio_set() (options prio, prioclass,
* and priohint) to be inherited.
* td->ioprio will have the value of the "default prio", so set
* this unconditionally. This value might get overridden by
* fio_ioring_cmdprio_prep() if the option cmdprio_percentage or
Expand Down
27 changes: 23 additions & 4 deletions fio.1
Original file line number Diff line number Diff line change
Expand Up @@ -2084,6 +2084,14 @@ is set, this defaults to the highest priority class. A single value applies
to reads and writes. Comma-separated values may be specified for reads and
writes. See man \fBionice\fR\|(1). See also the \fBprioclass\fR option.
.TP
.BI (io_uring,libaio)cmdprio_hint \fR=\fPint[,int]
Set the I/O priority hint to use for I/Os that must be issued with a
priority when \fBcmdprio_percentage\fR or \fBcmdprio_bssplit\fR is set.
If not specified when \fBcmdprio_percentage\fR or \fBcmdprio_bssplit\fR
is set, this defaults to 0 (no hint). A single value applies to reads and
writes. Comma-separated values may be specified for reads and writes.
See also the \fBpriohint\fR option.
.TP
.BI (io_uring,libaio)cmdprio \fR=\fPint[,int]
Set the I/O priority value to use for I/Os that must be issued with a
priority when \fBcmdprio_percentage\fR or \fBcmdprio_bssplit\fR is set.
Expand All @@ -2109,8 +2117,9 @@ The first accepted format for this option is the same as the format of the
cmdprio_bssplit=blocksize/percentage:blocksize/percentage
.RE
.P
In this case, each entry will use the priority class and priority level defined
by the options \fBcmdprio_class\fR and \fBcmdprio\fR respectively.
In this case, each entry will use the priority class, priority hint and
priority level defined by the options \fBcmdprio_class\fR, \fBcmdprio\fR
and \fBcmdprio_hint\fR respectively.
.P
The second accepted format for this option is:
.RS
Expand All @@ -2123,7 +2132,16 @@ entry. In comparison with the first accepted format, the second accepted format
does not restrict all entries to have the same priority class and priority
level.
.P
For both formats, only the read and write data directions are supported, values
The third accepted format for this option is:
.RS
.P
cmdprio_bssplit=blocksize/percentage/class/level/hint:...
.RE
.P
This is an extension of the second accepted format that allows to also
specify a priority hint.
.P
For all formats, only the read and write data directions are supported, values
for trim IOs are ignored. This option is mutually exclusive with the
\fBcmdprio_percentage\fR option.
.RE
Expand Down Expand Up @@ -3150,7 +3168,8 @@ I/O priority classes and to devices with features controlled through priority
hints, e.g. block devices supporting command duration limits, or CDL. CDL is a
way to indicate the desired maximum latency of I/Os so that the device can
optimize its internal command scheduling according to the latency limits
indicated by the user.
indicated by the user. For per-I/O priority hint setting, see the I/O engine
specific \fBcmdprio_hint\fB option.
.TP
.BI cpus_allowed \fR=\fPstr
Controls the same options as \fBcpumask\fR, but accepts a textual
Expand Down
13 changes: 10 additions & 3 deletions options.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,17 @@ static int parse_cmdprio_bssplit_entry(struct thread_options *o,
int matches = 0;
char *bs_str = NULL;
long long bs_val;
unsigned int perc = 0, class, level;
unsigned int perc = 0, class, level, hint;

/*
* valid entry formats:
* bs/ - %s/ - set perc to 0, prio to -1.
* bs/perc - %s/%u - set prio to -1.
* bs/perc/class/level - %s/%u/%u/%u
* bs/perc/class/level/hint - %s/%u/%u/%u/%u
*/
matches = sscanf(str, "%m[^/]/%u/%u/%u", &bs_str, &perc, &class, &level);
matches = sscanf(str, "%m[^/]/%u/%u/%u/%u",
&bs_str, &perc, &class, &level, &hint);
if (matches < 1) {
log_err("fio: invalid cmdprio_bssplit format\n");
return 1;
Expand All @@ -342,9 +344,14 @@ static int parse_cmdprio_bssplit_entry(struct thread_options *o,
case 2: /* bs/perc case */
break;
case 4: /* bs/perc/class/level case */
case 5: /* bs/perc/class/level/hint case */
class = min(class, (unsigned int) IOPRIO_MAX_PRIO_CLASS);
level = min(level, (unsigned int) IOPRIO_MAX_PRIO);
entry->prio = ioprio_value(class, level, 0);
if (matches == 5)
hint = min(hint, (unsigned int) IOPRIO_MAX_PRIO_HINT);
else
hint = 0;
entry->prio = ioprio_value(class, level, hint);
break;
default:
log_err("fio: invalid cmdprio_bssplit format\n");
Expand Down

0 comments on commit 79012fe

Please sign in to comment.