2 months agot/io_uring: don't print BW numbers for do_nop
Jens Axboe [Fri, 24 Sep 2021 21:17:44 +0000 (15:17 -0600)]
t/io_uring: don't print BW numbers for do_nop

They don't mean anything for nops, we're just interested in IOPS here.

Signed-off-by: Jens Axboe <>
2 months agot/io_uring: ensure batch counts are smaller or equal to depth
Jens Axboe [Thu, 23 Sep 2021 15:15:16 +0000 (09:15 -0600)]
t/io_uring: ensure batch counts are smaller or equal to depth

If you use a batch submit or complete count that's larger than the
depth, then t/io_uring will stall. Make sure to sanitize the counts
so that any batch values is always <= total depth.

Signed-off-by: Jens Axboe <>
2 months agoMerge branch 'one-core' of
Jens Axboe [Tue, 21 Sep 2021 00:29:40 +0000 (18:29 -0600)]
Merge branch 'one-core' of

* 'one-core' of
  t/ Adding script to run the one-core io benchmark

2 months agot/ Adding script to run the one-core io benchmark
Erwan Velu [Thu, 16 Sep 2021 20:52:22 +0000 (22:52 +0200)]
t/ Adding script to run the one-core io benchmark

Associated to fio, the t/io_uring test is used to compute the max IOPS a
single core can get.

Jens published several times the procedure he uses, but trying to
reproduce this setup is error-prone. It's easy to miss a configuration
and get a different result.

This script is about setting up a common setup to reproduce these runs.

From the fio directory, execute like the folliowing :

[user@fio] t/ /dev/nvme0n1 [other drives]
system: CPU: AMD EPYC 7502P 32-Core Processor
system: MEMORY: 2933 MT/s
system: KERNEL: 5.10.35-1.el8.x86_64
nvme0n1: MODEL=Samsung SSD 970 EVO Plus 2TB FW=2B2QEXM7 serial=S59CNM0R417706B PCI=0000:01:00.0@8.0 GT/s PCIe IRQ=64 NUMA=0 CPUS=0-23
nvme0n1: set none as io scheduler
nvme0n1: iostats set to 1.
nvme0n1: nomerge set to 0.
Warning: For better performance, you should enable nvme poll queues by setting nvme.poll_queues=32 on the kernel commande line

io_uring: Running taskset -c 0,12 t/io_uring -b512 -d128 -c32 -s32 -p1 -F1 -B1 -n4 /dev/nvme0n1
IOPS=731008, BWPS=356 MB IOS/call=32/31, inflight=(108 127 126 106)

This script will take care of the following items:
- nvme poll queues
- io scheduler
- iostats
- io_poll
- nomerge
- finding the logical cores running on the first physical core
- cpu frequency governor on performance
- cpu idle governor on menu
- calling t/io_uring with the proper parameters in 512 bytes fashion
- reporting the nvme & pci configuration

Signed-off-by: Erwan Velu <>
2 months agot/io_uring: fix bandwidth calculation
Jens Axboe [Thu, 16 Sep 2021 17:41:06 +0000 (11:41 -0600)]
t/io_uring: fix bandwidth calculation

Fixes: 22fd35012cea ("t/io_uring: Reporting bandwidth")
Signed-off-by: Jens Axboe <>
2 months agoMerge branch 'bwps' of
Jens Axboe [Thu, 16 Sep 2021 17:29:57 +0000 (11:29 -0600)]
Merge branch 'bwps' of

* 'bwps' of
  t/io_uring: Reporting bandwidth

2 months agot/io_uring: Reporting bandwidth
Erwan Velu [Thu, 16 Sep 2021 16:46:30 +0000 (18:46 +0200)]
t/io_uring: Reporting bandwidth

When performing tests at various block size, it's sometimes a bit
difficult to estimate if we reach the limit of the datapath.

This commit offer to simply prints the resulting bandwitdh of the IOPS
multiplied by the block size.

A typical output looks like :

  [user@hosŧ] t/io_uring -b512 -d128 -c32 -s32 -p1 -F1 -B1 -n4 /dev/nvme0n1
   IOPS=729856, BW=356 MiB/s, IOS/call=32/32, inflight=(105 119 108 109)

  [user@host] t/io_uring -b4096 -d128 -c32 -s32 -p1 -F1 -B1 -n4 /dev/nvme0n1
   IOPS=746368, BW=2915 MiB/s, IOS/call=32/31, inflight=(121 115 122 122)

In the 4K case, as for a PCI Gen3 product, we are clearly limited by the
bandwidth while in the 512 case we hit latency issues.

BW is expressed in MiB/sec.

Signed-off-by: Erwan Velu <>
2 months agot/io_uring: add switch -O for O_DIRECT vs buffered
Jens Axboe [Wed, 15 Sep 2021 12:51:01 +0000 (06:51 -0600)]
t/io_uring: add switch -O for O_DIRECT vs buffered

Signed-off-by: Jens Axboe <>
2 months agozbd: remove dead zone retrieval call
Jens Axboe [Mon, 13 Sep 2021 20:09:01 +0000 (14:09 -0600)]
zbd: remove dead zone retrieval call

A previous commit missed to realize that not only was the assignment
useless, that also made the very call to zbd_zone_nr() useless as
well. Remove it.

Fixes: 000ecb5fe36d ("zbd: Removing useless variable assignment")
Signed-off-by: Jens Axboe <>
2 months agot/io_uring: add -N option for do_nop
Jens Axboe [Mon, 13 Sep 2021 19:18:26 +0000 (13:18 -0600)]
t/io_uring: add -N option for do_nop

Makes it easier than asking people to edit and compile.

Signed-off-by: Jens Axboe <>
2 months agot/io_uring: don't require a file for do_nop runs
Jens Axboe [Mon, 13 Sep 2021 19:14:29 +0000 (13:14 -0600)]
t/io_uring: don't require a file for do_nop runs

Signed-off-by: Jens Axboe <>
2 months agoMerge branch 'ft' of
Jens Axboe [Wed, 8 Sep 2021 21:40:47 +0000 (15:40 -0600)]
Merge branch 'ft' of

* 'ft' of
  log: Removing useless assignment
  zbd: Removing useless variable assignment
  lib/fls.h: Remove unused variable assignment
  engines/sg: Removing useless variable assignment
  stat: Avoid freeing null pointer
  filesetup: Removing unused variable usage
  engines/sg: Return error if generic_close_file fails

2 months agolog: Removing useless assignment
Erwan Velu [Wed, 8 Sep 2021 21:10:50 +0000 (23:10 +0200)]
log: Removing useless assignment

The last len assigment is never read which makes it useless.

Signed-off-by: Erwan Velu <>
2 months agozbd: Removing useless variable assignment
Erwan Velu [Wed, 8 Sep 2021 21:00:45 +0000 (23:00 +0200)]
zbd: Removing useless variable assignment

zone_idx_b is set but never read again.

Signed-off-by: Erwan Velu <>
2 months agolib/fls.h: Remove unused variable assignment
Erwan Velu [Wed, 8 Sep 2021 20:52:10 +0000 (22:52 +0200)]
lib/fls.h: Remove unused variable assignment

x is modified just before the last set of r but x is never used again.
Let's remove this useless assignment.

Signed-off-by: Erwan Velu <>
2 months agoengines/sg: Removing useless variable assignment
Erwan Velu [Wed, 8 Sep 2021 20:43:39 +0000 (22:43 +0200)]
engines/sg: Removing useless variable assignment

ret is set to -1 but the break statement will not use this value.

So let's remove this useless assignment which could be confusing.

Signed-off-by: Erwan Velu <>
2 months agostat: Avoid freeing null pointer
Erwan Velu [Wed, 8 Sep 2021 20:35:59 +0000 (22:35 +0200)]
stat: Avoid freeing null pointer

If ovals is NULL, the jump to out will free(ovals) and will trigger an error.
As the out label was only used for this condition, let's remove it and return immediately.
As out was also used as a variable name, this makes the function easier
to read and more robust.

Signed-off-by: Erwan Velu <>
2 months agoREADME: add link to new lore archive
Jens Axboe [Wed, 8 Sep 2021 20:31:04 +0000 (14:31 -0600)]
README: add link to new lore archive

Signed-off-by: Jens Axboe <>
2 months agofilesetup: Removing unused variable usage
Erwan Velu [Wed, 8 Sep 2021 20:22:56 +0000 (22:22 +0200)]
filesetup: Removing unused variable usage

done is set to true but this is useless as break will
stop the while loop.

So let's remove this useless assignment.

Signed-off-by: Erwan Velu <>
2 months agoengines/sg: Return error if generic_close_file fails
Erwan Velu [Wed, 8 Sep 2021 20:18:53 +0000 (22:18 +0200)]
engines/sg: Return error if generic_close_file fails

The current code was returning 1 if generic_close_file() fails.
The ret value was prepared with the real error, let's return this one as
the per generic_open_file() error handling.

Signed-off-by: Erwan Velu <>
2 months agot/io_uring: ensure that nthreads is > 0
Jens Axboe [Wed, 8 Sep 2021 20:12:16 +0000 (14:12 -0600)]
t/io_uring: ensure that nthreads is > 0

Signed-off-by: Jens Axboe <>
2 months agot/io_uring: allow flexible IO threads assignment
Andrzej Jakowski [Wed, 8 Sep 2021 18:35:00 +0000 (11:35 -0700)]
t/io_uring: allow flexible IO threads assignment

This patch allows to flexibly assign IO threads to fileset. When
you specify:

t/io_uring -n 5 /dev/dev1 dev/dev2

First file/device will get 3 IO threads and second file/device
remaining 2 IO threads. When there is more files then IO threads,
IO thread may get assigned multiple files/devices.

Signed-off-by: Andrzej Jakowski <>
Signed-off-by: Jens Axboe <>
2 months agoFio 3.28 fio-3.28
Jens Axboe [Wed, 8 Sep 2021 14:59:48 +0000 (08:59 -0600)]
Fio 3.28

Signed-off-by: Jens Axboe <>
2 months agot/io_uring: don't make setrlimit() failing fatal
Jens Axboe [Wed, 8 Sep 2021 14:07:57 +0000 (08:07 -0600)]
t/io_uring: don't make setrlimit() failing fatal

We don't even need this on newer kernels, so just ignore it if it
fails. The worst that can happen is that buffer registration will

Signed-off-by: Jens Axboe <>
2 months agot/io_uring: fixes in output
Andrzej Jakowski [Wed, 8 Sep 2021 04:10:44 +0000 (21:10 -0700)]
t/io_uring: fixes in output

Provide description of available options in usage command
and fix alignment so they look pretty.

Also remove debug output.

Signed-off-by: Andrzej Jakowski <>
Signed-off-by: Jens Axboe <>
2 months agooptions: Add thinktime_iotime option
Shin'ichiro Kawasaki [Mon, 6 Sep 2021 01:50:00 +0000 (10:50 +0900)]
options: Add thinktime_iotime option

The thinktime option allows stalling a job for a specified amount of
time. Using the thinktime_blocks option, periodic stalls can be added
every thinktime_blocks IOs. However, with this option, the periodic
stall may not be repeated at equal time intervals as the time to execute
thinktime_blocks IOs may vary.

To control the thinktime interval by time, introduce the option
thinktime_iotime. With this new option, the thinktime stall is repeated
after IOs are executed for thinktime_iotime. If this option is used
together with the thinktime_blocks option, the thinktime pause is
repeated after thinktime_iotime or after thinktime_blocks IOs, whichever
happens first.

To support the new option, add a new member thinktime_iotime in the
struct thread_options and the struct thread_options_pack. Avoid size
increase of the struct thread_options_pack by replacing a padding 'pad5'
with the new member. To keep thinktime related members close, move the
members near the position where the padding was placed. Make same
changes to the struct thread_option also for consistency.

To track the time and IO block count at the last stall, add
last_thinktime variable and last_thinktime_blocks variable to struct
thread_data. Also, introduce the helper function init_thinktime()
to group thinktime related preparations.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
2 months agoexamples: add examples for cmdprio_* IO priority options
Damien Le Moal [Fri, 3 Sep 2021 15:20:27 +0000 (15:20 +0000)]
examples: add examples for cmdprio_* IO priority options

Add the example scripts cmdprio-percentage.fio and cmdprio-bssplit.fio
to illustrate the use of the cmdprio_percentage, cmdprio_class,
cmdprio and cmdprio_bssplit options. Also add the fiograph output
images for these example scripts.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agofio: Introduce the log_prio option
Damien Le Moal [Fri, 3 Sep 2021 15:20:26 +0000 (15:20 +0000)]
fio: Introduce the log_prio option

Introduce the log_prio option to expand priority logging from just a
single bit information (priority high vs low) to the full value of the
priority value used to execute IOs. When this option is set, the
priority value is printed as a 16-bits hexadecimal value combining
the I/O priority class and priority level as defined by the
ioprio_value() helper.

Similarly to the log_offset option, this option does not result in
actual I/O priority logging when log_avg_msec is set.

This patch also fixes a problem with the IO_U_F_PRIORITY flag, namely
that this flag is used to indicate that the IO is being executed with a
high priority on the device while at the same time indicating how to
account for the IO completion latency (high_prio clat vs low_prio clat).
With the introduction of the cmdprio_class and cmdprio options, these
assumptions are not necesarilly compatible anymore.

These problems are addressed as follows:
* The priority_bit field of struct iosample is replaced with the
  16-bits priority field representing the full io_u->ioprio value. When
  log_prio is set, the priority field value is logged as is. When
  log_prio is not set, 1 is logged as the entry's priority field if the
  sample priority class is IOPRIO_CLASS_RT, and 0 otherwise.
* IO_U_F_PRIORITY is renamed to IO_U_F_HIGH_PRIO to indicate that a job
  IO has the highest priority within the job context and so must be
  accounted as such using high_prio clat.

While fio final statistics only show accounting of high vs low IO
completion latency statistics, the log_prio option allows a user to
perform more detailed statistical analysis of a workload using
multiple different IO priorities.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agolibaio,io_uring: relax cmdprio_percentage constraints
Damien Le Moal [Fri, 3 Sep 2021 15:20:26 +0000 (15:20 +0000)]
libaio,io_uring: relax cmdprio_percentage constraints

In fio, a job IO priority is controlled with the prioclass and prio
options and these options cannot be used together with the
cmdprio_percentage option.

Allow a user to have async IO priorities default to the job defined
IO priority by removing the mutual exclusion between the options
cmdprio_percentage and prioclass/prio.

With the introduction of the cmdprio_class option, an async IO priority
may be lower than the job default priority, resulting in reversed clat
statistics showed for high and low priority IOs when fio completes.
Solve this by setting an io_u IO_U_F_PRIORITY flag depending on a
comparison between the async IO priority and job default IO priority.

When an async IO is issued without a priority set, Linux kernel will
execute it using the IO priority of the issuing context set with
ioprio_set(). This works fine for libaio, where the context will be
the same as the context that submitted the IO.

However, io_uring can be used with a kernel thread that performs
block device IO submissions (sqthread_poll). Therefore, for io_uring,
an IO sqe ioprio field must be set to the job default priority unless
the IO priority is set according to the job cmdprio_percentage value.

Because of this, IO uring already did set sqe->ioprio even when only
prio/prioclass was used. See commit b7ed2a862dda ("io_uring: set sqe
iopriority, if prio/prioclass is set"). In order to make the code easier
to maintain, handle all I/O priority preparations in the same function.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agolibaio,io_uring: introduce cmdprio_bssplit
Damien Le Moal [Fri, 3 Sep 2021 15:20:25 +0000 (15:20 +0000)]
libaio,io_uring: introduce cmdprio_bssplit

The cmdprio_percentage, cmdprio_class and cmdprio options allow
specifying different values for read and write operations. This enables
various IO priority issuing patterns even uner a mixed read-write
workload but does not allow differentiation within read and write
I/O operation types with different sizes when the bssplit option is

Introduce the cmdprio_bssplit option to complement the use of the
bssplit option.  This new option has the same format as the bssplit
option, but the percentage values indicate the percentage of I/O
operations with a particular block size that must be issued with the
priority class and value specified by cmdprio_class and cmdprio.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agolibaio,io_uring: introduce cmdprio_class and cmdprio options
Damien Le Moal [Fri, 3 Sep 2021 15:20:24 +0000 (15:20 +0000)]
libaio,io_uring: introduce cmdprio_class and cmdprio options

When the cmdprio_percentage option is used, the specified percentage of
IO will be issued with the highest priority class IOPRIO_CLASS_RT. This
priority class maps to the ATA NCQ "high" priority level and allows
exercising a SATA device to measure its command latency characteristics
in the presence of low and high priority commands.

Beside ATA NCQ commands, Linux block IO schedulers also support IO
priorities and will behave differently in the presence of IOs with
different IO priority classes and values. However, cmdprio_percentage
does not allow specifying all possible priority classes and values.

To solve this, introduce libaio and io_uring engine specific options
cmdprio_class and cmdprio. These new options are the equivalent
of the prioclass and prio options and allow specifying the priority
class and priority value to use for asynchronous I/Os when the
cmdprio_percentage option is used. If not specified, the I/O priority
class defaults to IOPRIO_CLASS_RT and the I/O priority value to 0,
as before. Similarly to the cmdprio_percentage option, these options
can specify different values for read and write I/Os using a comma
separated list.

The manpage, HOWTO and fiograph configuration file are updated to
document these new options.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agolibaio,io_uring: improve cmdprio_percentage option
Damien Le Moal [Fri, 3 Sep 2021 15:20:24 +0000 (15:20 +0000)]
libaio,io_uring: improve cmdprio_percentage option

The cmdprio_percentage option of the libaio and io_uring engines defines
a single percentage that applies to all IO operations, regardless of
their direction. This prevents defining different high priority IO
percentages for reads and writes operations. This differentiation can
however be useful in the case of a mixed read-write workload (rwmixread
and rwmixwrite options).

Change the option definition to allow specifying a comma separated list
of percentages, 2 at most, one for reads and one for writes. If only a
single percentage is defined, it applies to both reads and writes as
before. The cmdprio_percentage option becomes an array of DDIR_RWDIR_CNT
elements indexed with enum fio_ddir values. The last entry of the array
(for DDIR_TRIM) is always 0.

Also create a new cmdprio helper file, engines/cmdprio.h,
such that we can avoid code duplication between io_uring and libaio
io engines. This helper file will be extended in subsequent patches.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agooptions: make parsing functions available to ioengines
Damien Le Moal [Fri, 3 Sep 2021 15:20:23 +0000 (15:20 +0000)]
options: make parsing functions available to ioengines

Move the declaration of split_parse_ddir(), str_split_parse() and
the split_parse_fn typedef to thread_options.h so that IO engines
can use these functions to parse options. The definition of struct
split is also moved to thread_options.h from options.c.

The type of the split_parse_fn callback function is changed to add a
void * argument that can be used for an option parsing callback to pass
a private data pointer to the split_parse_fn function. This can be used
by an IO engine to pass a pointer to its engine specific option
structure as td->eo is not yet set when options are being parsed.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agoos: introduce ioprio_value() helper
Damien Le Moal [Fri, 3 Sep 2021 15:20:23 +0000 (15:20 +0000)]
os: introduce ioprio_value() helper

Introduce the ioprio_value() helper function to calculate a priority
value based on a priority class and priority level. For Linux and
Android, this is defined as an integer equal to the priority class
shifted left by 13 bits and or-ed with the priority level. For
Dragonfly, ioprio_value() simply returns the priority level as there
is no concept of priority class.

Use this new helper in the io_uring and libaio engines to set IO
priority when the cmdprio_percentage option is used.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agotools: fiograph: do not overwrite input script file
Damien Le Moal [Fri, 3 Sep 2021 15:20:22 +0000 (15:20 +0000)]
tools: fiograph: do not overwrite input script file

In, the setup_commandline() function mistakenly initializes
the output_file variable to the input fio script file, causing this file
to always be overwritten, even if an output file is specified using the
--output option. Fix this by properly initializing the output_file
variable using the --output option argument value. If an output file
name is not provided, the input script file name is used by default.

Also fix fiograph configuration file to remove the cmdprio_percentage
option repeated entry for io_uring and libaio.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agomanpage: fix definition of prio and prioclass options
Damien Le Moal [Fri, 3 Sep 2021 15:20:21 +0000 (15:20 +0000)]
manpage: fix definition of prio and prioclass options

Remove the reference to the hipri_percentage option in the definition of
the prio and prioclass options as hipri_percentage controls the use of
RWF_HIPRI flag which triggers I/O completion polling, which is unrelated
with I/O priority (polling and I/O priority can be used together). This
change is done in both fio man page and HOWTO document.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agomanpage: fix formatting
Damien Le Moal [Fri, 3 Sep 2021 15:20:20 +0000 (15:20 +0000)]
manpage: fix formatting

For ioengine options supported by multiple ioengines, remove spaces
after commas in the ioengine list to have troff correctly format in bold
the entire ioengine list and option name. Also add "=int" indicators
missing for some options.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
2 months agooslib: Fix blkzoned_get_max_open_zones()
Damien Le Moal [Wed, 1 Sep 2021 06:41:53 +0000 (15:41 +0900)]
oslib: Fix blkzoned_get_max_open_zones()

When the kernel does not have the sysfs atttribute file
queue/max_open_zones, blkzoned_get_max_open_zones() returns success
without initializing the max_open_zones value to 0 to indicate to the
caller (zbd_get_max_open_zones() in zbd.c) that the device limit is
unknown. If the max_open_zones variable in zbd_get_max_open_zones() is
not already 0 (depending on the memory status), the missing
initialization in blkzoned_get_max_open_zones() can cause errors or
misbehavior as an incorrect, random, limit may be used.

Fix this by always initializing max_open_zones to 0 when the
max_open_zones sysfs attribute file does not exist.

Reported-by: Bao-Hua Li <>
Signed-off-by: Damien Le Moal <>
Signed-off-by: Jens Axboe <>
2 months agot/io_uring: further simplify inflight tracking
Jens Axboe [Sat, 28 Aug 2021 21:37:25 +0000 (15:37 -0600)]
t/io_uring: further simplify inflight tracking

Don't dump the last submitter inflight as well, just use file_depths()
for all of them.

Signed-off-by: Jens Axboe <>
3 months agot/io_uring: pretty up multi-file depths
Jens Axboe [Fri, 27 Aug 2021 18:44:02 +0000 (12:44 -0600)]
t/io_uring: pretty up multi-file depths

Signed-off-by: Jens Axboe <>
3 months agoio_uring: don't clear recently set sqe->rw_flags
Niklas Cassel [Thu, 26 Aug 2021 16:45:05 +0000 (16:45 +0000)]
io_uring: don't clear recently set sqe->rw_flags

Commit 7c70f506e438 ("engines/io_uring: move sqe clear out of hot path")
removed the memset of sqe from fio_ioring_prep().

This commit did add a clear of the sqe->rw_flags, however, it did so
after both RWF_UNCACHED and RWF_NOWAIT flags might have been set,
effectively clearing these flags if they got set.

This doesn't make any sense. Make sure that we clear sqe->rw_flags
before, not after, setting the flags.

Fixes: 7c70f506e438 ("engines/io_uring: move sqe clear out of hot path")
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
3 months agoio_uring: fix misbehaving cmdprio_percentage option
Niklas Cassel [Thu, 26 Aug 2021 16:45:05 +0000 (16:45 +0000)]
io_uring: fix misbehaving cmdprio_percentage option

Commit 7c70f506e438 ("engines/io_uring: move sqe clear out of hot path")
removed the memset of sqe from fio_ioring_prep().

Before this commit, fio_ioring_prio_prep() behaved properly, because
sqe->ioprio was always cleared by the memset in fio_ioring_prep().

cmdprio_percentage=20 is supposed to set the highest priority class for
20% of the total I/Os, however, because sqes got reused without clearing
the ioprio field, this meant that the number of I/Os sent with the highest
priority became 95% already after 10 seconds. Quite far off from the
intended 20%.

Fix this by explicitly clearing the priority in fio_ioring_prio_prep().
Note that prio/prioclass cannot be used together with cmdprio_percentage,
so we do not need to do an additional clear in fio_ioring_prep().

engines/libaio.c doesn't explicitly clear the ioprio, nor does it memset
the descriptor entry, this is because io_prep_pread()/io_prep_pwrite() in
libaio itself performs a memset.

Fixes: 7c70f506e438 ("engines/io_uring: move sqe clear out of hot path")
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
3 months agoio_uring: always initialize sqe->flags
Niklas Cassel [Thu, 26 Aug 2021 16:45:04 +0000 (16:45 +0000)]
io_uring: always initialize sqe->flags

Commit 7c70f506e438 ("engines/io_uring: move sqe clear out of hot path")
removed the memset of sqe from fio_ioring_prep().

Later, force_async was added in commit 5a59a81d2923 ("engines/io_uring:
allow setting of IOSQE_ASYNC").

The force_async commit sets sqe->flags every N requests, however,
since we no longer do a memset, this commit should have made sure that
flags is always initialized, such that we don't have sqe->flags set on
reused sqes where we didn't intend to.

Fixes: 5a59a81d2923 ("engines/io_uring: allow setting of IOSQE_ASYNC")
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
3 months agoMerge branch 'wip-cxx' of
Jens Axboe [Thu, 26 Aug 2021 14:46:36 +0000 (08:46 -0600)]
Merge branch 'wip-cxx' of

* 'wip-cxx' of
  arch,lib/seqlock: implement seqlock with C++ atomic if compiled with C++

3 months agoarch,lib/seqlock: implement seqlock with C++ atomic if compiled with C++
Kefu Chai [Wed, 11 Aug 2021 04:29:39 +0000 (12:29 +0800)]
arch,lib/seqlock: implement seqlock with C++ atomic if compiled with C++

because some functions declared by <stdatomic.h> share the same names
with those declared by <atomic>, for instance `kill_dependency()` is
defined as a macro by <stdatomic.h>, while it is defined as a template
function in <atomic>.

this renders it impossible to compile an ioengine written in C++ if
its source file includes both <atomic> and <fio.h>. the latter includes
<stdatomic.h> via arch/arch.h. the compile error would look like:

In file included from ../src/test/fio/
In file included from src/fio/fio.h:18:
In file included from src/fio/thread_options.h:8:
In file included from src/fio/gettime.h:7:
src/fio/lib/seqlock.h:21:9: error: expected ')'
                seq = atomic_load_acquire(&s->sequence);
src/fio/arch/../lib/../arch/arch.h:47:32: note: expanded from macro 'atomic_load_acquire'
        atomic_load_explicit((_Atomic typeof(*(p)) *)(p),       \
src/fio/lib/seqlock.h:21:9: note: to match this '('

to address this issue, instead of using the functions in <stdatomic.h> to
implement seqlock, use the primitives offered by C++ standard library
if the source code is compiled using a C++ compiler.

Signed-off-by: Kefu Chai <>
3 months agoMerge branch 'master' of
Jens Axboe [Sat, 21 Aug 2021 02:58:42 +0000 (20:58 -0600)]
Merge branch 'master' of

* 'master' of
  fixed type boot->bool

3 months agofixed type boot->bool
Damon Palovaara [Fri, 20 Aug 2021 22:22:58 +0000 (15:22 -0700)]
fixed type boot->bool

3 months agoMerge branch 'patch-1' of
Jens Axboe [Wed, 18 Aug 2021 16:47:55 +0000 (10:47 -0600)]
Merge branch 'patch-1' of

* 'patch-1' of
  server: reopen standard streams to /dev/null

3 months agoserver: reopen standard streams to /dev/null
Andreas Economides [Wed, 18 Aug 2021 12:19:51 +0000 (13:19 +0100)]
server: reopen standard streams to /dev/null

For some custom ioengines (see,
it's not trivial to suppress output to stdout and stderr, so they would
write to some other file descriptor fio had opened - which is bad.

This change ensures that fd's 0, 1, and 2 (stdin, stdout, stderr) are
always valid and can be used without any unintended consequences.

Signed-off-by: Andreas Economides <>
3 months agoMerge branch 'dfs_update_13_api' of
Jens Axboe [Fri, 13 Aug 2021 16:01:31 +0000 (10:01 -0600)]
Merge branch 'dfs_update_13_api' of

* 'dfs_update_13_api' of
  engines/dfs: add support for 1.3 DAOS API

3 months agot/io_uring: allow multiple IO threads
Jens Axboe [Wed, 11 Aug 2021 22:54:23 +0000 (16:54 -0600)]
t/io_uring: allow multiple IO threads

If you do:

t/io_uring -n2 /dev/dev1 /dev/dev2

then t/io_uring will create two IO threads, and each one will get
a file/device assigned. In the above example, thread 1 will run
on dev1, thread 2 on dev2.

Note that for now, you'll need at least as many files as threads.
Adding support for adding the same file set over the specified
threads (if we have less files than threads) is left as an
exercise for the reader. You know where to send the patches.

Signed-off-by: Jens Axboe <>
3 months agoengines/dfs: add support for 1.3 DAOS API
Johann Lombardi [Tue, 10 Aug 2021 13:03:21 +0000 (15:03 +0200)]
engines/dfs: add support for 1.3 DAOS API

A few changes were done to the pool connect and container open API
in DAOS 1.3+. UUID string or label are now passed via the API
instead of uuid_t structures. Change the dfs engine accordingly.

Signed-off-by: Johann Lombardi <>
3 months agot/zbd: Add test #58 to test zone reset by trim workload
Shin'ichiro Kawasaki [Fri, 6 Aug 2021 01:07:11 +0000 (10:07 +0900)]
t/zbd: Add test #58 to test zone reset by trim workload

To exercise zone reset by trim workload, add the test case #58. As the
precondition, it fills several zones. After that, a trim job and a write
job run in parallel for 30 seconds. The ratio of trim commands and write
commands is controlled by --flow option.

Signed-off-by: Shin'ichiro Kawasaki <>
Tested-by: Dmitry Fomichev <>
Reviewed-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
3 months agoHOWTO/man: Describe trim support by zone reset for zoned devices
Shin'ichiro Kawasaki [Fri, 6 Aug 2021 01:07:10 +0000 (10:07 +0900)]
HOWTO/man: Describe trim support by zone reset for zoned devices

Previous commits added trim support for zoned devices. Update HOWTO and
man page to describe it. Also add missing description about libzbc I/O
engine to HOWTO.

Signed-off-by: Shin'ichiro Kawasaki <>
Reviewed-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
3 months agoengines/libzbc: Enable trim for libzbc I/O engine
Shin'ichiro Kawasaki [Fri, 6 Aug 2021 01:07:09 +0000 (10:07 +0900)]
engines/libzbc: Enable trim for libzbc I/O engine

The trim workload to zoned block devices is supported as zone reset, and
this feature is available for I/O engines which support both zoned
devices and trim workload. Libzbc I/O engine supports zoned devices but
lacks trim workload support. To enable trim support with libzbc I/O
engine, remove the check which inhibited trim from requests to libzbc
I/O engine. Also set file open flags for trim same as write, and call
zbd_do_io_u_trim() for trim I/O.

Of note is that libzbc I/O engine now can support trim to sequential
write required zones only. The trim I/Os to conventional zones are
reported as an error.

Signed-off-by: Shin'ichiro Kawasaki <>
Reviewed-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
3 months agozbd: Support zone reset by trim
Shin'ichiro Kawasaki [Fri, 6 Aug 2021 01:07:08 +0000 (10:07 +0900)]
zbd: Support zone reset by trim

Enable trim workload for zonemode=zbd by modifying do_io_u_trim() to
call zoned block device unique function zbd_do_io_u_trim() which resets
the target zone. This allows fio to emulate workloads which mix data
read/write and zone resets with zonemode=zbd.

To call reset zones, the trim I/O shall have offset aligned to zone
start and block size same as zone size. Reset zone is called only to
sequential write required zones and sequential write preferred zones.
Conventional zones are handled in same manner as regular block devices
by calling os_trim() function.

When zones are reset with random trim workload, choose only non-empty
zones as trim target. This avoids meaningless trim to empty zones and
makes the workload more realistic. To find the non-empty zones, utilize
zbd_find_zone() helper function which is already used for read workload,
specifying 1 byte as the minimum valid data size.

Signed-off-by: Shin'ichiro Kawasaki <>
Reviewed-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
3 months agozbd: Add min_bytes argument to zbd_find_zone()
Shin'ichiro Kawasaki [Fri, 6 Aug 2021 01:07:07 +0000 (10:07 +0900)]
zbd: Add min_bytes argument to zbd_find_zone()

The helper function zbd_find_zone() finds a zone with at least
min_bs[DDIR_READ] bytes of readable data before the zone write pointer.
This patch generalizes this function to allow finding a non-empty zone.
To do so, add the min_bytes argument to specify the minimum readable
data of a zone to filter the search. Specifying 1 to min_bytes then
become equivalent to finding a non-empty zone.

This change will allow to reuse this function to find a suitable zone
for trim I/O.

Signed-off-by: Shin'ichiro Kawasaki <>
Reviewed-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
3 months agoioengines: fix crash with --enghelp option
Vincent Fu [Wed, 4 Aug 2021 18:29:05 +0000 (18:29 +0000)]
ioengines: fix crash with --enghelp option

Since f6931a1dd35896433c8cc2e10de51372a2c496c4 commands like the
following segfault:

fio --enghelp=sg
fio --enghelp=sg,sg_write_mode

This is because free_ioengine() assumes that td->io_ops is not NULL.
Make this true when free_ioengine() is called by
fio_show_ioengine_help() to avoid the crash.

Signed-off-by: Vincent Fu <>
Signed-off-by: Jens Axboe <>
3 months agobackend: clarify io scheduler setting error message
Vincent Fu [Wed, 4 Aug 2021 18:29:04 +0000 (18:29 +0000)]
backend: clarify io scheduler setting error message

If you know *how* fio tries to confirm that the IO scheduler was
successfully set, then the error message "io scheduler not found" makes
sense. However, if you don't know what fio does to confirm the io
scheduler setting, then the error message is confusing. This patch
modifies the error message to indicate that the selected IO scheduler
could not be set.

Signed-off-by: Vincent Fu <>
Signed-off-by: Jens Axboe <>
3 months agozbd: Improve random zone index generation logic
Ankit Kumar [Wed, 4 Aug 2021 11:23:08 +0000 (16:53 +0530)]
zbd: Improve random zone index generation logic

Existing random zone index generation logic is dependent on the file size.
For smaller I/O sizes the random zone index always return a particular
section of open zones. As this index is used to return one of the open zones,
it was observed that after one of the max_open_zones / job_max_open_zones limit
is reached all further I/O's are redirected to only a few open zones till they
are full.

This patch modifies the random zone index genration logic so that it is uniform
across all the open zones.

It reverts part of the commit 6463db6c1
('fio: fix interaction between offset/size limited threads and

Tested-by: Shin'ichiro Kawasaki <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Ankit Kumar <>
Signed-off-by: Jens Axboe <>
3 months agoHOWTO: Add missing documentation for job_max_open_zones
Ankit Kumar [Wed, 4 Aug 2021 11:23:07 +0000 (16:53 +0530)]
HOWTO: Add missing documentation for job_max_open_zones

Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Ankit Kumar <>
Signed-off-by: Jens Axboe <>
3 months agofio: remove raw device support
Eric Sandeen [Tue, 3 Aug 2021 17:23:35 +0000 (10:23 -0700)]
fio: remove raw device support

As of Linux kernel commit 603e4922f1c ("remove the raw driver"),
linux/raw.h is gone, and raw device support no longer exists.
Because of this, fio can no longer build against the current Linux
kernel headers.

So, remove raw device support from fio as well.

Signed-off-by: Eric Sandeen <>
Signed-off-by: Jens Axboe <>
3 months agoiolog: don't attempt read chunking with blktrace format
Jens Axboe [Mon, 2 Aug 2021 14:23:24 +0000 (08:23 -0600)]
iolog: don't attempt read chunking with blktrace format

Signed-off-by: Jens Axboe <>
3 months agoMerge branch 'master' of
Jens Axboe [Sun, 1 Aug 2021 14:36:01 +0000 (08:36 -0600)]
Merge branch 'master' of

* 'master' of
  Fix an error triggered by double releasing the lock

3 months agoFix an error triggered by double releasing the lock
anson-lo [Sun, 1 Aug 2021 04:33:22 +0000 (12:33 +0800)]
Fix an error triggered by double releasing the lock

Fix an error triggered by double releasing the lock.

Signed-off-by: Anson Lo
4 months agoMakefile: update libzbc git repository
Damien Le Moal [Wed, 28 Jul 2021 07:05:42 +0000 (16:05 +0900)]
Makefile: update libzbc git repository

Update the GIT repository used for libzbc in the fulltes directive from
pointing to the now deprecated hgst reporitory to the currentxi repository.

Signed-off-by: Damien Le Moal <>
Signed-off-by: Jens Axboe <>
4 months agoMerge branch 'evelu-fix-engines' of
Jens Axboe [Sun, 25 Jul 2021 22:48:02 +0000 (16:48 -0600)]
Merge branch 'evelu-fix-engines' of

* 'evelu-fix-engines' of
  engines/exec: Code cleanup to remove leaks

4 months agoengines/exec: Code cleanup to remove leaks
Erwan Velu [Sun, 25 Jul 2021 22:01:18 +0000 (00:01 +0200)]
engines/exec: Code cleanup to remove leaks

As per the coverty reports, there was some issues in my code :
- Some structures were not properly freed before returning.
- Some file descriptors were not properly closed
- Testing with 'if (!int)' isn't a good way to test if the value is negative

Signed-off-by: Erwan Velu <>
4 months agoengines/exec: style cleanups
Jens Axboe [Sun, 25 Jul 2021 18:55:37 +0000 (12:55 -0600)]
engines/exec: style cleanups

No functional changes in this patch.

Signed-off-by: Jens Axboe <>
4 months agoMerge branch 'evelu-exec' of
Jens Axboe [Sun, 25 Jul 2021 15:37:35 +0000 (09:37 -0600)]
Merge branch 'evelu-exec' of

* 'evelu-exec' of
  fiograph: Adding exec engine support
  engines: Adding exec engine

4 months agoMerge branch 'dedupe_workset' of
Jens Axboe [Thu, 15 Jul 2021 15:54:03 +0000 (09:54 -0600)]
Merge branch 'dedupe_workset' of

* 'dedupe_workset' of
  dedupe: allow to generate dedupe buffers from working set

4 months agoMerge branch 'cmd-test-be' of
Jens Axboe [Thu, 15 Jul 2021 15:26:01 +0000 (09:26 -0600)]
Merge branch 'cmd-test-be' of

* 'cmd-test-be' of
  server: fix missing le32_to_cpu conversion when opcode is FIO_NET_CMD_TEXT

4 months agoserver: fix missing le32_to_cpu conversion when opcode is FIO_NET_CMD_TEXT
Tuan Hoang [Thu, 15 Jul 2021 13:57:31 +0000 (15:57 +0200)]
server: fix missing le32_to_cpu conversion when opcode is FIO_NET_CMD_TEXT

Reported-by: Manuel Gotin <>
Signed-off-by: Tuan Hoang <>
4 months agodedupe: allow to generate dedupe buffers from working set
Bar David [Thu, 17 Jun 2021 12:39:58 +0000 (15:39 +0300)]
dedupe: allow to generate dedupe buffers from working set

This commit introduced new dedupe generation mode "working_set".
Working set mode simulates a more realistic approach to deduped data,
in which deduped buffers are generated from pre-existing working set -
% size of the device or file.

In other words, dedupe is not usually expected to be close
in time with the source buffer, as well as source buffers
are usually composed of small subset of the entire file or device.

Signed-off-by: Bar David <>
4 months agoMakefile: use override directive on engine CFLAGS
Stefan Hajnoczi [Tue, 6 Jul 2021 17:27:00 +0000 (18:27 +0100)]
Makefile: use override directive on engine CFLAGS

The GNU Make documentation says the following about the override

  Subsequent assignments or appends to this variable which are not
  marked override will be ignored.

When the override CFLAGS line was moved in commit
f4bd2c3d80bc35f76892205a7e50426711e3def3 it broke the engine template,
which does not use the override directive. Since the engine template is
now evaluated afterwards, the engine CFLAGS are ignored.

Add the override keyword to the engine template so that engine CFLAGS
are honored again.

Note that the CONFIG_DYNAMIC_ENGINES case doesn't need the override
directive. It seems that GNU Make assigns CFLAGS even without the
override directive in this case:

  $$($(1)_OBJS): CFLAGS := -fPIC $$($(1)_CFLAGS) $(CFLAGS)

Fixes: f4bd2c3d80bc35f76892205a7e50426711e3def3 ("fix dynamic engine build")
Cc: Eric Sandeen <>
Signed-off-by: Stefan Hajnoczi <>
Signed-off-by: Jens Axboe <>
4 months agoMerge branch 'dedupe_bugfix' of
Jens Axboe [Thu, 1 Jul 2021 19:27:39 +0000 (13:27 -0600)]
Merge branch 'dedupe_bugfix' of

* 'dedupe_bugfix' of
  dedupe: fixing bug with subsequent dedupe buffer generation

4 months agodedupe: fixing bug with subsequent dedupe buffer generation
Bar David [Thu, 1 Jul 2021 13:32:52 +0000 (16:32 +0300)]
dedupe: fixing bug with subsequent dedupe buffer generation

When unique pages are generated onto the write buffer the seed
used to generate the page is copied later to the buf_state_prev
for future dedupe generation.

However, the get_buf_state API returns pointer to the prev
seed. Then when the caller uses it to re-generate the buffer
it changes the internal seed and advances the PRNG.
A subsequent intention to create another dedup might result in
generating a unique page instead.

Signed-off-by: Bar David <>
4 months agofiograph: Adding exec engine support
Erwan Velu [Tue, 29 Jun 2021 14:23:43 +0000 (16:23 +0200)]
fiograph: Adding exec engine support

Since fiograph is merged, let's add the specific options of this engine
into it and render the example job.

Signed-off-by: Erwan Velu <>
4 months agoengines: Adding exec engine
Erwan Velu [Wed, 12 May 2021 07:54:11 +0000 (09:54 +0200)]
engines: Adding exec engine

When performing benchmarks with fio, some need to execute
tasks in parallel to the job execution. A typical use-case would be
observing performance/power metrics.

Several implementations were possible :
 - Adding an exec_run in addition of the existing exec_{pre|post}run
 - Implementating performance/power metrics in fio
 - Adding an exec engine

1°) Adding an exec_run
This was my first intention but quickly noticed that exec_{pre-post}run
are executed for each 'numjob'. In the case of performance/power
monitoring, this doesn't make sense to spawn an instance for each

2°) Implementing performance/power metrics
This is possible but would require lot of work to maintain this part of
fio while 3rd party tools already take care of that perfectly.

3°) Adding an engine
Adding an engine let users defining when and how many instances of the program they want.
In the provided example, a single monitoring job is spawning at the same
time as the worker thread which could be composed of several worker
A stonewall barrier is used to define which jobs must run together
(monitoring / benchmark).

The engine has two parameters :
- program: name of the program to run
- arguments: arguments to pass to the program
- grace_time: duration between SIGTERM and SIGKILL
- std_redirect: redirect std{err|out} to dedicated files

Arguments can have special variables to be expanded before the execution:
- %r will be replaced by the job duration in seconds
- %n will be replaced by the job name

During the program execution, the std{out|err} are redirected to files if std_redirect option is set (default).
- stdout: <job_name>.stdout
- stderr: <job_name>.stderr

If the executed program has a nice stdout output, after the fio
execution, the stdout file can be parsed by other tools like CI jobs or graphing tools.

A sample job is provided here to show how this can be used.
It runs twice the CPU engine with two different CPU modes (noop vs qsort).
For each benchmark, the output of turbostat is saved for later analysis.
After the fio run, it is possible to compare the impact of the two modes
on the CPU frequency and power consumption.

This can be easily extended to any other usage that needs to analysis
the behavior of the host during some jobs.

About the implementation, the exec engine forks :
- the child doing an execvp() of the program.
- the parent, fio, will monitor the time passed into the job

Once the time is over, the program is SIGTERM followed by a SIGKILL to
ensure it will not run _after_ the job is completed.
This mechanism is required as :
- not all programs can be controlled properly
- that's last resort protection if the program gets crazy
The delay is controlled by grace_time option, default is 1 sec.

If the program can be limited in its duration, using the %r variable in
the arguments can be used to request the program to stop _before_ the
job finished like :
        arguments=--duration %r

Signed-off-by: Erwan Velu <>
4 months agozbd: ensure that global max open zones limit is respected
Niklas Cassel [Thu, 24 Jun 2021 17:23:08 +0000 (17:23 +0000)]
zbd: ensure that global max open zones limit is respected

Commit 219c662d3b12 ("zbd: introduce per job maximum open zones limit")
Introduced a global max open zones limit stored in zbd_info->max_open_zones.

This commit also changed checks against td->o.max_open_zones in zbd_open_zone()
with checks against zbd_info->max_open_zones.

It is obvious that zbd_info->max_open_zones was intended to replace
td->o.max_open_zones in all code that is executed after zbd_setup_files().

The commit itself was needed since zbd_info is shared over different jobs,
so it is important that the global limit of max open zones is the same,
for different jobs targeting the same device.

The problem with this commit is that in zbd_convert_to_open_zone(),
instead of replacing td->o.max_open_zones with zbd_info->max_open_zones,
it incorrectly just removed the references to td->o.max_open_zones.

This caused commit 00ca8df5468e ("zbd: Fix max_open_zones checks")
(written by another author) to incorrectly re-add the removed
td->o.max_open_zones checks in zbd_convert_to_open_zone().
The proper fix here should have been to add checks against
zbd_info->max_open_zones instead of td->o.max_open_zones,
just like the original author did for zbd_open_zone().

Replace all td->o.max_open_zones uses past zbd_setup_files() with
zbd_info->max_open_zones, and force set td->o.max_open_zones to
zbd_info->max_open_zones in zbd_setup_files(), so that even if checks are
introduced against the wrong limit, fio will still respect the global limit.

Fixes: 00ca8df5468e ("zbd: Fix max_open_zones checks")
Reviewed-by: Damien Le Moal <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Niklas Cassel <>
Cc: Alexey Dobriyan <>
Cc: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 months agozbd: allow an unlimited global max open zones limit
Niklas Cassel [Thu, 24 Jun 2021 17:23:07 +0000 (17:23 +0000)]
zbd: allow an unlimited global max open zones limit

Commit 219c662d3b12 ("zbd: introduce per job maximum open zones limit")
Introduced a global max open zones limit stored in zbd_info->max_open_zones.

This commit also removed the following check from zbd_open_zone():

if (!td->o.max_open_zones)
        return true;

Before the commit in question, if td->o.max_open_zones == 0, zbd_open_zone()
would not track the zone as open in the zbd_info->open_zones array.

After the commit in question, zbd_open_zone() would always track the zone
as open in the zbd_info->open_zones array, regardless if a --max_open_zones
limit was set or not.

Change the initialization of zbd_info->max_open_zones to yet again allow
unlimited max open zones. If zbd_info->max_open_zones is unlimited,
we do not track the open zones in the zbd_info->open zone array.

Not tracking open zones reduces fio overhead for testing the performance of
zoned block devices that do not have a limit on the maximum number of open

Reviewed-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Cc: Alexey Dobriyan <>
Signed-off-by: Jens Axboe <>
4 months agozbd: create a local zbdi variable for f->zbd_info
Niklas Cassel [Thu, 24 Jun 2021 17:23:07 +0000 (17:23 +0000)]
zbd: create a local zbdi variable for f->zbd_info

Create a local zbdi variable for f->zbd_info for the following functions:
zbd_open_zone(), zbd_convert_to_open_zone(), and zbd_adjust_block().

This avoids unnecessary indirections.

No functional change intended.

Reviewed-by: Damien Le Moal <>
Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
4 months agoMerge branch 'evelu-fiog' of
Jens Axboe [Tue, 29 Jun 2021 13:38:33 +0000 (07:38 -0600)]
Merge branch 'evelu-fiog' of

* 'evelu-fiog' of
  examples: Avoid duplicated items
  tools: Adding fiograph

5 months agoexamples: Avoid duplicated items
Erwan Velu [Sun, 27 Jun 2021 21:06:03 +0000 (23:06 +0200)]
examples: Avoid duplicated items

Some jobs were defining variable twice,
some jobs were defined twice.

This commit ensure that examples are items are named only once.

Signed-off-by: Erwan Velu <>
5 months agotools: Adding fiograph
Erwan Velu [Wed, 16 Jun 2021 13:16:25 +0000 (15:16 +0200)]
tools: Adding fiograph

This tool generates graphviz graphs of any fio job file.

Reading a fio file can be sometimes tricky when :
  - you have lots of jobs
  - jobs override some options
  - jobs have dependencies

Understanding which jobs are running at the same time, which one waits
for which is sometimes difficult and could easily lead to mistakes.
It's pretty common to find jobs where people think jobs are sequential
while some run in parallel.

For ease the understanding of the scheduling and what's the
configuration status (local + global variables), this tool will use some
graphical helpers to enlighten things.

The configuration file can be used to adjust the rendering but by default :
  - jobs are defined in a blue rounded box
  - jobs running at the same time are inside the same gray background
  - time & size variables are shown as a self arrow
  - dependencies between jobs are shown by up->down black arrows
  - specific engines options are written in blue (top of the job box)
  - standard options are printed in green (bottom of the job box)
  - pre/post actions are printed in red (head/tail of the job box)
  - numjobs is replaced by a 'x' multiplicator on the job name

Several output formats can be defined via --format : list can be found

if --view option is used, the rendered file will be immediately shown.

if --keep is used, the grapvhiz file will be kept.

This commit also adds the rendering of the examples jobs.
If a newcomer gets into the repository, they can immediately better
understand what the jobs do.

Signed-off-by: Erwan Velu <>
5 months agoMerge branch 'pkg_config_1' of
Jens Axboe [Sun, 20 Jun 2021 16:44:49 +0000 (10:44 -0600)]
Merge branch 'pkg_config_1' of

* 'pkg_config_1' of
  configure: silence "pkg-config: not found"

5 months agofilehash: ignore hashed file with fd == -1
Jens Axboe [Thu, 17 Jun 2021 16:55:20 +0000 (10:55 -0600)]
filehash: ignore hashed file with fd == -1

This can happen sporadically during setup, and it need not be a
failure condition.

Signed-off-by: Jens Axboe <>
5 months agot/zbd: update test case 42
Niklas Cassel [Mon, 14 Jun 2021 13:49:05 +0000 (13:49 +0000)]
t/zbd: update test case 42

Update test case 42 to grep for the new string printed by fio when
--zonesize=0 is supplied.

Signed-off-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
5 months agozbd: change some f->zbd_info conditionals to asserts
Niklas Cassel [Mon, 14 Jun 2021 13:49:05 +0000 (13:49 +0000)]
zbd: change some f->zbd_info conditionals to asserts

Unfortunately, generic fio code calls some zbd_* functions unconditionally.
These functions will be called regardless if zonemode == ZONE_MODE_NONE,
ZONE_MODE_STRIDED or ZONE_MODE_ZBD, and cannot be optimized.

However, some functions are only called when zonemode == ZONE_MODE_ZBD.
Since f->zbd_info will always be non-NULL for a job with zonemode=zbd,
these functions can be optimized to not check if f->zbd_info is set.

Signed-off-by: Niklas Cassel <>
Reviewed-by: Damien Le Moal <>
Signed-off-by: Jens Axboe <>
5 months agozbd: remove zbd_zoned_model ZBD_IGNORE
Niklas Cassel [Mon, 14 Jun 2021 13:49:04 +0000 (13:49 +0000)]
zbd: remove zbd_zoned_model ZBD_IGNORE

For a job with zonemode=zbd, we do not want any file to be ignored.
Each file's file type in that job should be supported by either zbd.c
or the ioengine. If not, we should return an error.
This way, ZBD_IGNORE becomes redundant and can be removed.

By removing ZBD_IGNORE, we know that all files belonging to a job that
has zonemode=zbd set, will either be a zoned block device, or emulate
a zoned block device.

This means that for jobs that have zonemode=zbd, f->zbd_info will always
be non-NULL. This will make the zbd code slightly easier to reason about
and to maintain.

When removing zbd_zoned_model ZBD_IGNORE, define the new first enum value
as 0x1, so that we avoid potential ABI problems with existing binaries.

Signed-off-by: Niklas Cassel <>
Reviewed-by: Damien Le Moal <>
Signed-off-by: Jens Axboe <>
5 months agozbd: allow zonemode=zbd with regular files by emulating zones
Niklas Cassel [Mon, 14 Jun 2021 13:49:04 +0000 (13:49 +0000)]
zbd: allow zonemode=zbd with regular files by emulating zones

Currently when using zonemode=zbd and running against a regular file,
fio will fail with:
fio: file hash not empty on exit

Treat regular files just like how we treat regular (non-zoned) block
devices: return ZBD_NONE and let zbd.c emulate zones inside the regular
file/block device.

Signed-off-by: Niklas Cassel <>
Reviewed-by: Damien Le Moal <>
Signed-off-by: Jens Axboe <>
5 months agozbd: disallow pipes for zonemode=zbd
Niklas Cassel [Mon, 14 Jun 2021 13:49:03 +0000 (13:49 +0000)]
zbd: disallow pipes for zonemode=zbd

zoned block device support in fio cannot handle pipes,
so simply reject them and give a clear error message.

Signed-off-by: Niklas Cassel <>
Reviewed-by: Damien Le Moal <>
Signed-off-by: Jens Axboe <>
5 months agoio_uring: drop redundant IO_MODE_OFFLOAD check
Stefan Hajnoczi [Thu, 10 Jun 2021 15:55:39 +0000 (16:55 +0100)]
io_uring: drop redundant IO_MODE_OFFLOAD check

check_engine_ops() already returns an error if io_submit_mode is
IO_MODE_OFFLOAD and the engine is marked FIO_NO_OFFLOAD.

Signed-off-by: Stefan Hajnoczi <>
Signed-off-by: Jens Axboe <>
5 months agot/zbd: Fix write target zones counting in test case #31
Shin'ichiro Kawasaki [Fri, 4 Jun 2021 11:32:52 +0000 (20:32 +0900)]
t/zbd: Fix write target zones counting in test case #31

The test case #31 in t/zbd/test-zbd-support writes 128KB data to
sequential write required zones as the preparation for the following
random read test. The data write leaves the target zones in open status.
The test case refers the variable 'nz', which has max_open_zones value,
to decide how many zones to write the data. However, the end condition
of the write target zone loop has a bug. The disk end offset is used as
the loop end condition, which does not match the last target zone when
number of sequential write required zones divided by nz has remainder.
This results in write to more zones than nz=max_open_zones limit and the
test case failure. To fix the bug and to simplify the script, avoid the
loop and utilize zonemode strided to achieve the same data write
pattern. Also specify size and io_size using nz to reliably count the
write target zones.

Even with the fix above, still the number of open zones may exceed
max_open_zones since other test cases executed before the test case 31
may leave open zones on the test target device. To avoid this failure,
reset all zones before the data write.

The failures were observed with libzbc I/O engine after the commit
e8267436fd7a ("engines/libzbc: add support for the get_max_open_zones io
op"), which changed the max_open_zones value fio refers.

Signed-off-by: Shin'ichiro Kawasaki <>
Reviewed-by: Damien Le Moal <>
Reviewed-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
5 months agot/zbd: Add ignore_zone_limit option to test with special max_open_zones
Shin'ichiro Kawasaki [Fri, 4 Jun 2021 11:32:51 +0000 (20:32 +0900)]
t/zbd: Add ignore_zone_limit option to test with special max_open_zones

Recent commit d2f442bc0bd5 ("ioengines: add get_max_open_zones zoned
block device operation") modified fio to compare --max_open_zones option
value and max_open_zones reported by the device. When the option
--max_open_zones is larger than the device limit, fio exits with an
error. However, sometimes it is useful to run fio with --max_open_zones
larger than the device limit to check performance impact of implicit
zone open and close by the zoned block devices. The test script
t/zbd/test-zbd-support has an option -o so that users can specify such
larger max_open_zones value. After the commit, such test runs fail with
the fio error.

To avoid the failure, modify the test script to specify another option
--ignore_zone_limits to fio command, which was added by the commit
575686bb85fa (zbd: add a new --ignore_zone_limits option). This option
is added to fio command only when users specify -o option and special
max_open_zones value to the test script. This change does not affect
default test conditions.

Signed-off-by: Shin'ichiro Kawasaki <>
Reviewed-by: Damien Le Moal <>
Reviewed-by: Niklas Cassel <>
Signed-off-by: Jens Axboe <>
5 months agot/zbd: Use max_open_zones that fio fetched from device
Shin'ichiro Kawasaki [Fri, 4 Jun 2021 11:32:50 +0000 (20:32 +0900)]
t/zbd: Use max_open_zones that fio fetched from device

Recent commit d2f442bc0bd5 ("ioengines: add get_max_open_zones zoned
block device operation") modified fio to compare --max_open_zones option
value and max_open_zones reported by the device. The device limit is
fetched through sysfs or through an ioengine specific implementation.

The test script currently try to fetch the max open zones limit using
libzbc tools or sg_inq. If either of these fail, default value 128 is
supplied. This default value can be too high when the test script is
run for certain zoned block devices, and can therefore result in fio
error and test case failure.

To avoid the failure, modify the default value used in the test script
from 128 to 0. With this, --max_open_zones=0 is passed to fio, and it
makes fio use the max_open_zones reported by the device. Also add
comments to describe why the test script gets max_open_zones with tools.

Reviewed-by: Niklas Cassel <>
Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
5 months agoconfigure: silence "pkg-config: not found"
Tomohiro Kusumi [Tue, 8 Jun 2021 17:14:34 +0000 (02:14 +0900)]
configure: silence "pkg-config: not found"

Do what check_min_lib_version() does to not print the error message
when pkg-config doesn't exist.

DAOS File System (dfs) Engine no
./configure: pkg-config: not found
NFS engine                    no

Signed-off-by: Tomohiro Kusumi <>
5 months agoMerge branch 'fix/928' of
Jens Axboe [Thu, 3 Jun 2021 15:01:52 +0000 (09:01 -0600)]
Merge branch 'fix/928' of

* 'fix/928' of
  fix fio2gnuplot to work with new logging format

5 months agoMerge branch 'evelu-test' of
Jens Axboe [Thu, 3 Jun 2021 13:45:22 +0000 (07:45 -0600)]
Merge branch 'evelu-test' of

* 'evelu-test' of
  Makefile: Avoid using built-in stpcpy during clang build
  ci: Reporting installed msys2 packages
  ci: Installing missing toolchain

5 months agoMakefile: Avoid using built-in stpcpy during clang build
Erwan Velu [Wed, 2 Jun 2021 14:15:59 +0000 (16:15 +0200)]
Makefile: Avoid using built-in stpcpy during clang build

Since clang 12, during the clang build, noticed by the CI, the linking
fails as clang optimize some string functions to stpcpy.

  LINK fio
lld-link: error: undefined symbol: stpcpy
>>> referenced by C:\projects\fio\options.c:5305
>>>               options.o:(fio_options_parse)

Two possible implementations :
- Adding stpcpy in fio as the kernel did :
- Disable the implicit stpcpy

To avoid adding code into fio, the latter option was used.

Signed-off-by: Erwan Velu <>