backend: correctly handle rate_iops combined with bssplit

Currently, rate_iops does not produce the expected I/O rate with
workloads that use 'bssplit' option. Consider the following example
configuration -

[global]
direct=1
time_based
runtime=30s
ioengine=io_uring
thread=1

[bssplit_rate_iops_repro]
filename=/dev/sdX
rw=randread
iodepth=8
bs=64K
rate_iops=50

This works correctly and ~50 IOPS I/O rate is logged during the run.

If we replace 'bs=64K' with the following bssplit option -

bssplit=32ki/20:64ki/40:256ki/10:512ki/25:1mi/5

in the configuration above, then some incorrect (much lower) IOPS values
are observed to be in effect at run time.

This problem happens because fio, in order to derive the required
I/O rate from 'rate_iops' value provided by the user, simply multiplies
the IOPS value by the minimum block size (min_bs). Once bps I/O rate is
calculated this way, the processing for 'rate' and 'rate_iops' becomes
identical.

This works if the I/O issued has the uniform min_bs, as in case of using
'bs=64K'. However, with 'bssplit' option in effect, fio may issue I/O
with sizes that are much different from min_bs. Yet the code in
usec_for_io() currently always calculates I/O issue delays based on
min_bs leading to incorrect IOPS being produced.

Fix this by modifying usec_for_io() function to check for
bssplit+rate_iops being in effect. For this case, derive the IOPS rate
from bps 'rate' member of thread data and then calculate the delay to
the next I/O using the IOPS value, not the bps rate.

Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://patch.msgid.link/20260310205804.477935-1-dmitry.fomichev@wdc.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 file changed