11 days agoAdd a new file to gitignore master
Hongwei Qin [Sun, 21 Feb 2021 09:39:44 +0000 (17:39 +0800)]
Add a new file to gitignore

Add t/fuzz/fuzz_parseini to the ignore list.

Signed-off-by: Hongwei Qin <>
Signed-off-by: Jens Axboe <>
2 weeks agoengines/io_uring: add verbose error for ENOSYS
Jens Axboe [Tue, 16 Feb 2021 19:07:14 +0000 (12:07 -0700)]
engines/io_uring: add verbose error for ENOSYS

If we get ENOSYS for setting up the rings, then the kernel is too old
to support io_uring. Mention that explicitly.

Signed-off-by: Jens Axboe <>
2 weeks agoMerge branch 'per-engine-pre-write-function' of
Jens Axboe [Sun, 14 Feb 2021 20:21:05 +0000 (13:21 -0700)]
Merge branch 'per-engine-pre-write-function' of

* 'per-engine-pre-write-function' of
  filesetup: add engine's io_ops to prepopulate file with data

3 weeks agoMerge branch 'taras/clientuid' of
Jens Axboe [Wed, 10 Feb 2021 20:22:04 +0000 (13:22 -0700)]
Merge branch 'taras/clientuid' of

* 'taras/clientuid' of
  $clientuid keyword to differentiate clients in client/server mode.

3 weeks ago$clientuid keyword to differentiate clients in client/server mode.
Taras Glek [Wed, 10 Feb 2021 19:08:52 +0000 (11:08 -0800)]
$clientuid keyword to differentiate clients in client/server mode.

Prior to this change getting fio to include IP as part of filename was a struggle. One had to use directory=/ to trigger IP-inclusion code and there was no way to customize that.

Signed-off-by: Taras Glek <>
3 weeks agofilesetup: add engine's io_ops to prepopulate file with data
Łukasz Stolarczuk [Fri, 22 Jan 2021 12:12:43 +0000 (13:12 +0100)]
filesetup: add engine's io_ops to prepopulate file with data

In some cases (e.g. engine marked as diskless) files are not laid out.
If the first job is a read job, results are higher than expected
(because reading zero page). Each engine should deliver func to
prepopulate file with data to avoid this situation.

Signed-off-by: Łukasz Stolarczuk <>
4 weeks agozbd: relocate Coverity annotation
Dmitry Fomichev [Sat, 30 Jan 2021 03:35:24 +0000 (12:35 +0900)]
zbd: relocate Coverity annotation

The Coverity annotation added earlier to suppress a false positive
about missing unlock in zbd_adjust_block() didn't work because it
was placed not before the return statement, but earlier in the code.

Move the annotation to the right place to avoid the warning.

Reported-by: Bart Van Assche <>
Fixes: 8e4b2e55512f("zbd: don't unlock zone mutex after verify replay")
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: fix 32-bit compile warnings for logging
Jens Axboe [Fri, 29 Jan 2021 19:20:48 +0000 (12:20 -0700)]
zbd: fix 32-bit compile warnings for logging

Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: avoid looping on invalid command line options
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:45 +0000 (13:19 +0900)]
t/zbd: avoid looping on invalid command line options

t/zbd/test-zbd-support loops indefinitely if an unrecognized option
is specified in the command line. Add a switch case to display usage
and exit the script.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: increase timeout in test #48
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:44 +0000 (13:19 +0900)]
t/zbd: increase timeout in test #48

Test #48 runs some i/o to the test device for 30 seconds and then waits
45 seconds for fio to finish. If this wait times out, the test assumes
that fio is hung because of a zone locking issue and fails. It is
observed that 45s may not be enough for some HDDs, especially the ones
running specialized firmware.

Increase the timeout to 180 seconds to avoid any false positives.
There is no change in test duration for the most common devices.
The test will wait for the full 180 seconds only if it fails, otherwise
it will finish very soon after the 30 second i/o period ends.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: show elapsed time in test-zbd-support
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:43 +0000 (13:19 +0900)]
t/zbd: show elapsed time in test-zbd-support

This script may take quite a lot of time to run against large
zoned HDDs. At the end of every run, show exactly how much time
it took.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: add test #54 to exercise ZBD verification
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:42 +0000 (13:19 +0900)]
t/zbd: add test #54 to exercise ZBD verification

Add a new test case to perform 75/25 read/write workload with varying
i/o size and verification on. It is very important to use a good random
generator for this test. Setting experimental_verify=1 is required for
this test to operate correctly.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: add checks for offline zone condition
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:41 +0000 (13:19 +0900)]
t/zbd: add checks for offline zone condition

Some tests, e.g. #39 an #40, try to read the first zone of the drive.
It is assumed that the first zone is readable. However, if the first
zone is offline, the read fails along with the entire test.

This commit adds two functions to perform zone report and find the
first and the last zones that are not offline. Several test cases
now call these functions to avoid test failures described above.

Fixes for two more test failures are included in this commit -

Test #14 tries to write to conventional zones if they are found at
the beginning of the LBA range of the drive, but it assumes that
these zones are online. This may not always be the case. Add "offset"
to avoid the i/o to be attempted to run against any preceding offline

Similarly, in test #17, the script tries to find the last zone.
Check for the case when the last zone is offline. The test doesn't
set the i/o file size, but it works OK in most of the cases because
typically this test operates on the last physical zone. With the
online lookup in place, this may not always be the case and if there
are any offline zones that trail the last non-offline zone,
then the i/o will try to access that zone and fail. Add the "size"
to avoid the i/o to be attempted to run against any trailing offline

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: prevent test #31 from looping
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:40 +0000 (13:19 +0900)]
t/zbd: prevent test #31 from looping

The test 31 starts i/o to 128 zones in parallel.
There are two corner cases that are not properly handled in the
existing implementation -
1) If the total number of zones on the device is < 128, the test
will loop indefinitely because the loop increment is calculated as
zero by the script.
2) If the number of max_open_zones of the device is < 128, the
test will fail due to exceeding max_open_zones limit as the code
expects it to be >= 128.

Limit the number of open zones to the reported maximum
and skip the test if there is not enough zones on the device.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: add an option to bail on a failed test
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:39 +0000 (13:19 +0900)]
t/zbd: add an option to bail on a failed test

Sometimes, it can be useful to inspect the state of the zones of the
test device, usually right after a test failure. Currently,
test-zbd-support script just keeps running and proper examination of
device zones can be difficult.

Add the -q option to test/zbd/support to quit immediately upon
encountering any test failure. Additionally, define the same option
in run-tests-against-nullb to propagate it to test/zbd/support.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: fix wrong units in test case #37
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:38 +0000 (13:19 +0900)]
t/zbd: fix wrong units in test case #37

The second argument of the function total_zone_capacity is expected to
be in bytes. However, the call in test case #37 provides this argument
in sectors and this results in a wrong capacity calculation. Make sure
that the value that is passed to this function is converted to bytes.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: test random I/O direction in all-conventional case
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:37 +0000 (13:19 +0900)]
t/zbd: test random I/O direction in all-conventional case

The number of 'sectors with data' is counted and used to determine the
direction of the first I/O of a random read/write ZBD workload. To
initialize the number, min_zone and max_zone fields in struct fio_file
are referred. There was a code bug that was recently fixed where
min_zone and max_zone fields were not initialized when all zones in I/O
region were conventional zones. This led to an uninitialized number of
sectors with data, and the write direction was always set for random

Add a test case to perform random read/write workload on an I/O region
with both sequential and conventional zones. Check that both read and
write I/Os are executed.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: test that zone_reset_threshold calculation is correct
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:36 +0000 (13:19 +0900)]
t/zbd: test that zone_reset_threshold calculation is correct

The option "zone_reset_threshold" specifies the ratio of logical blocks
with data to trigger zone resets. When the I/O range includes
conventional zones, only blocks in sequential zones must be used to
track this value. A recently fixed bug has uncovered that the number of
blocks in conventional zones were erroneously counted as the blocks
with data.

To prevent future regressions, add a test case to confirm that the
logical blocks accounting does not include conventional zones.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: test that conventional zones are not locked during random i/o
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:35 +0000 (13:19 +0900)]
t/zbd: test that conventional zones are not locked during random i/o

A recently fixed bug was caused by an unexpected conventional zone lock
during random I/O adjustment. Only sequential zones are supposed to be
locked, but the conventional zone lock was observed with a random
workload against an I/O region with mixed conventional and sequential

Add two test cases with the same workload to ensure that no similar
regression happens in the future. One case tests reads and the other
is for writes. As a related change, add the helper function
require_conv_zones() to check that the test target device has enough
conventional zones available.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: skip tests that need too many sequential zones
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:34 +0000 (13:19 +0900)]
t/zbd: skip tests that need too many sequential zones

Test cases #3, #4, #28, #29 and #48 require rather large numbers of
sequential zones to run properly and they fail if the test target
device has not enough of such zones in its zone configuration.

Check how many sequential zones are present on the test device and
skip any test cases for which this number is not enough.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: skip tests when test prerequisites are not met
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:33 +0000 (13:19 +0900)]
t/zbd: skip tests when test prerequisites are not met

Some of the test cases in t/zbd/test-zbd-support require test target
devices to have certain features. When these prerequisites are not met,
they skip the actual test and report the test result to be "PASS".
This does not help users to understand the true test outcome.
As the tests expand to cover a wider variety of zoned devices and
layouts, reporting skipped tests becomes more and more beneficial.

Modify test-zbd-support script to report skipped test cases.
Introduce helper functions require_*() to check test target
prerequisites. If they are not met, set the variable SKIP_REASON and
return the constant SKIP_TESTCASE from the test function. In the main
loo, print "SKIP" status and SKIP_REASON if the test case is skipped.
Also, output the total number of skipped cases at the end of the test
script  run.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: add -t option to run-tests-against-nullb
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:32 +0000 (13:19 +0900)]
t/zbd: add -t option to run-tests-against-nullb

For debugging, it can be useful to run a single ZBD test case in all
zoned configurations defined in run-tests-against-nullb. Add -t option
to run-tests-against-nullb so that the single ZBD test case specified
in run-tests-against-nullb command line is executed in all sections
of the script.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: add run-tests-against-nullb script
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:31 +0000 (13:19 +0900)]
t/zbd: add run-tests-against-nullb script

This script combines the t/zbd/run-tests-against-zoned-nullb script
functionality with t/zbd/run-tests-against-regular-nullb and adds
more zoned device configurations to test. This considerably improves
ZBD test coverage.

The added script makes the two old scripts named above obsolete,
remove them. Modify t/ and Makefile to refer to the
new script instead of the old one. Since the full test now runs
significantly longer than the two old ones combined due to many more
zoned configurations, only execute a few individual sections as a
part of testing n "make fulltest" and One extra test
section with 10% conventional zones is executed from the Makefile.
The Python tests only exercise all-conventional and all-sequential
configurations, exactly as before.

The script returns a non-zero return code if at least one of the
executed sections had a failed test.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agot/zbd: check for error in test #2
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:30 +0000 (13:19 +0900)]
t/zbd: check for error in test #2

With the preceding commit in place, fio gives an error if user attempts
to run write I/O size that is larger than the zone size. Grep for that
message instead of checking that no write has happened.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: set thread errors in zbd_adjust_block()
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:29 +0000 (13:19 +0900)]
zbd: set thread errors in zbd_adjust_block()

Several error conditions that are encountered during zone processing
in zbd_adjust_block() function cause it to return io_u_eof value.
This stops the i/o to the given file, but there is no error raised or
reported if this code is returned. For a few particular conditions,
just stopping the i/o is reasonable, but others are serious errors
that should be reported.

Add td_verror() calls to raise thread errors for a few abnormal
conditions during adjusting the i/o. The only test that needs to be
modified because of this changes is test #2.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: avoid failing assertion in zbd_convert_to_open_zone()
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:28 +0000 (13:19 +0900)]
zbd: avoid failing assertion in zbd_convert_to_open_zone()

The test run against null_blk with the following command line -

t/zbd/run-tests-against-nullb -l -q -s 12 -t 51 -n 100

stops with a failure and the message below can be seen in the test log:

fio: zbd.c:1110: zbd_convert_to_open_zone: Assertion `open_zone_idx < f->zbd_info->num_open_zones' failed.

This assertion fails because pick_random_zone_idx() function returns
index 0 if no zones are currently open. In this case, open_zone_idx and
f->zbd_info->num_open_zones are both zero. Since this situation is
normal, simply modify the assert statement to avoid failing.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agoengines/libzbc: enable block backend
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:27 +0000 (13:19 +0900)]
engines/libzbc: enable block backend

When opening a device, the current version of libzbc ioengine instructs
libzbc to only try SCSI and ATA backends for scanning the drive. This
prevents opening null_blk devices that fail to be accepted by the both
above mentioned backends and require the block backend to be enabled.

Set the appropriate flag to enable the block backend in zbc_open()
libzbc call.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: improve replay range validation
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:26 +0000 (13:19 +0900)]
zbd: improve replay range validation

The function zbd_replay_write_order() is called when a read is
issued by fio verification code to compare the read data with the
previously written data. Any data mismatch is marked as a verification

Since zbd_adjust_block() may change the i/o offset and length
to comply with i/o constrains that zoned model has set,
zbd_replay_write_order() needs to replicate the same adjustment during
verify. The general flow in this function matches the write processing
done in zbd_adjust_block(), but there are some differences. For
example, z->verify_block acts as the pseudo-write pointer during replay
and it needs to be advanced by buflen every time the function called,
but it is advanced by min_bs in the existing code (the value of this
variable is measured in min_bs units).

Fix the issue with verify_block and add more error logging to simplify
troubleshooting of this tricky part of ZBD code.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: handle conventional start zone in zbd_convert_to_open_zone()
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:25 +0000 (13:19 +0900)]
zbd: handle conventional start zone in zbd_convert_to_open_zone()

At the beginning of zbd_convert_to_open_zone() function, a zone
is picked in semi-random manner to become a candidate zone for
redirecting the incoming write. In some circumstances, such as
unlimited MaxOpen or i/o range that spans the boundary between
conventional and sequential zones, a conventional zone may be

This may create problems in the subsequent for (;;) loop in the
same function. Failed assertions were observed during the execution
of newly introduced test #51 that showed that the code in that loop
was trying to lock and unlock conventional zones.

Check if the zone which has been initially picked is conventional.
If yes, force the zone selection to be re-tried until a sequential
zone is selected for further processing.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: don't log "zone nnnn is not open" message
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:24 +0000 (13:19 +0900)]
zbd: don't log "zone nnnn is not open" message

This log message has been added recently (it could have been my idea
to add it during internal review) and it turns out that the message
tends to flood the log when any decent workload is run with
--zonemode=zbd. Remove logging of this debug message.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: disable crossing from conventional to sequential zones
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:23 +0000 (13:19 +0900)]
zbd: disable crossing from conventional to sequential zones

Write I/Os to conventional zones may have the range that spans across
zone boundaries. Such writes may cause I/O errors when its next zone
is a sequential zone.

To avoid such I/O errors, check for the cross over from a conventional
to a sequential zone. When the write crosses the boundary, shrink the
I/O length to fit within the first zone. If the offset is too close to
the end of the zone, wrap it around to the beginning of the same zone.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: use zone_lock() in zbd_process_swd()
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:22 +0000 (13:19 +0900)]
zbd: use zone_lock() in zbd_process_swd()

Most of ZBD code in fio uses zone_lock() to lock write pointer zones.
This wrapper, besides doing the obvious pthread mutex lock, quiesce
the outstanding i/o when running via asynchronous ioengines. This is
necessary to avoid deadlocks. The function zbd_process_swd(), however,
still uses the naked pthread mutex to lock zones and this leads to a
deadlock when running ZBD test #48 against regular nullb devices.

The fix added in the same patch series that introduced test #48 was to
NOT initialize SWD at all, but this solution is found to create
problems with verify. As the proper fix, modify zbd_process_swd()
to use zone_lock(). This makes the test #48 pass even when SWD counter
is initialized.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: initialize sectors with data at start time
Aravind Ramesh [Wed, 27 Jan 2021 04:19:21 +0000 (13:19 +0900)]
zbd: initialize sectors with data at start time

Based on the flag enable_check_swd, which is false by default, fio
does not initialize the swd value at startup, initializing the swd
value to be zero, even if some zones have sectors with data. This can
result in fio reflecting less than actual swd after a few writes are
completed. In workloads where verify is enabled, fio resets all the
zones and while resetting, it decrements the swd counter with the
actual number of swds in that zone(swd-count - swd-in-zone),
since swd-count is initialized to 0, it results in overflow of the
variable causing unpredictable issues.

So, initialize the swd to the correct value.

Fixes: 409a4f291e7f ("zbd: avoid initializing swd when unnecessary")
Signed-off-by: Aravind Ramesh <>
Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: initialize min_zone and max_zone for all zone types
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:20 +0000 (13:19 +0900)]
zbd: initialize min_zone and max_zone for all zone types

The function zbd_verify_sizes() checks if the given I/O range includes
write pointer zones. When all zones in the I/O range are conventional,
it skips checks for size options and leaves min_zone and max_zone in
struct fio_file with zero values. These uninitialized min_zone and
max_zone fields trigger unexpected behaviors such as unset

Fix this by moving min_zone and max_zone set up from zbd_verify_sizes()
to zbd_setup_files(). This allows for setting up the values regardless
of zone types in I/O range.

Bypass the assertion to ensure that max_zone is larger than min_zone if
all zones in the I/O range are conventional. In this case, io_size
can be smaller than zone size and, consequently, min_zone may become
the same as max_zone.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: count sectors with data for write pointer zones
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:19 +0000 (13:19 +0900)]
zbd: count sectors with data for write pointer zones

ZBD fio code tracks 'sectors with data' for two different purposes.
The first one is to process zone_reset_threshold. When the ratio of
sectors with data in zones with write pointer goes beyond the specified
number, zone reset is triggered. The second purpose is to control the
direction of the first I/O of random mixed read/write workloads. If all
write pointer zones in the I/O range are reset at the beginning of such
a workload, fio has no data to read and will immediately end the run of
the test section. To avoid this, fio checks 'sectors with data' and if
it is zero (i.e. it is the very first I/O), it modifies the direction
of that I/O from read to write.

Currently, when the workload range includes both conventional and
sequential zones, all sectors in conventional zones are counted as
'sectors with data' along with sectors in sequential zones.
This leads to incorrect handling  of 'zone_reset_threshold' option -
zone reset timing of sequential zones is affected by the amount of
data read from or written to conventional zones. To avoid this,
conventional zones should be excluded from 'sectors with data'

On the other hand, if the sectors of conventional zones were excluded
from the sectors with data, it could result in the wrong initial I/O
direction for random workloads. When the zones in I/O region are all
conventional, 'sectors with data' would always be zero. Because of
this, read operations are always changed to writes and reads are never

To avoid this contradiction, introduce another counter,
'wp_sector_with_data'. It works similar to the existing
'sectors_with_data', but it counts data sectors only in write pointer
zones. Use this newly introduced count for zone_reset_threshold checks
and keep on using the original count for the initial random I/O
direction determination.

When counting sectors with data, lock only write pointer zones, no need
to lock conventional zones.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: do not set zbd handlers for conventional zones
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:18 +0000 (13:19 +0900)]
zbd: do not set zbd handlers for conventional zones

When zbd_adjust_block() modifies io_u to satisfy write pointer
restrictions, it may change the zone for the io_u. The function sets
pointers to zbd_queue_io() and zbd_put_io() handlers to io_u to
further process write pointer zones. However, when the I/O is
redirected to a conventional zone, these handlers should not
be set in io_u.

Skip setting the handlers when this function returns a conventional
zone. When zbd_adjust_block() can not find a zone to fit the I/O,
the existing code unlocks the zone pointer 'zb' used in the function.
This unlock should not be performed if 'zb' points to a conventional
zone upon return, skip it in this case.

These changes make the assert for 'zb' pointer near 'accept' label in
zbd_adjust_block() unnecessary. Replace it with assert for zb->has_wp,
since the zone at the step shall have write pointer.

Since zone locking functions (zone_lock(), zbd_queue_io() and
zbd_put_io()) are supposed to be called only for write pointer zones,
add assertions to zone_lock() and zone_unlock() to make sure this is
the case. This allows us to convert a few existing conditional checks
to assertions to make zone type validation more strict.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: do not lock conventional zones on I/O adjustment
Shin'ichiro Kawasaki [Wed, 27 Jan 2021 04:19:17 +0000 (13:19 +0900)]
zbd: do not lock conventional zones on I/O adjustment

When a random workload runs against write pointer zones, I/Os are
adjusted to meet write pointer restrictions. During read, I/O offsets
are adjusted to point to zones with data to read and during write, I/O
offsets are adjusted to be at write pointers of open zones.

However, when a random workload runs in a range that contains both
write pointer zones and conventional zones, I/Os to write pointer
zones can potentially be adjusted to conventional zones. The functions
zbd_find_zone() and zbd_convert_to_open_zone() search for zones
regardless of their type, and therefore they may return conventional
zones. These functions lock the found zone to guard its open status
and write pointer position, but this lock is meaningless for
conventional zones. This unwanted lock of conventional zones has been
observed to cause a deadlock.

Furthermore, zbd_convert_to_open_zone() may add the found conventional
zone to the array of open zones. However, conventional zones should
never be added to the array of open zones as conventional zones never
take the "implicit open" condition and not counted as part of the
device open zone management.

To avoid the deadlock, modify zbd_find_zone() not to lock zone when it
checks conventional zone without write pointer. To avoid the deadlock
and the conventional zone open, modify zbd_convert_to_open_zone() to
ignore conventional zones.

Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Dmitry Fomichev <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: don't unlock zone mutex after verify replay
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:16 +0000 (13:19 +0900)]
zbd: don't unlock zone mutex after verify replay

zbd_adjust_block() always returns with the zone locked if the i/o is
accepted. The corresponding unlock happens in zbd_put_io(). The
function description says -

 * Locking strategy: returns with z->mutex locked if and only if z refers
 * to a sequential zone and if io_u_accept is returned. z is the zone that
 * corresponds to io_u->offset at the end of this function.

Remove the recently added unlock after zbd_replay_write_order() call.
Add a Coverity annotation to mark the absence of unlock as intentional.

Fixes: b2726d53bb5d ("zbd: Add a missing pthread_mutex_unlock() call")
Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: avoid zone buffer overrun
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:15 +0000 (13:19 +0900)]
zbd: avoid zone buffer overrun

If the total number of zones on a drive is calculated to a value that
is less than the number of zones it can actually report, zone info
buffer can be overrun. This may happen not only due to drive firmware
problems, but also because of underlying software incorrectly
reporting zoned device capacity.

Fix this by more carefully setting zone report size.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: skip offline zones in zbd_convert_to_open_zone()
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:14 +0000 (13:19 +0900)]
zbd: skip offline zones in zbd_convert_to_open_zone()

Since all I/Os to an offline zone will fail, add a check in
zbd_convert_to_open_zone() to ignore zones that have this condition.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: remove dependency on zone type during i/o
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:13 +0000 (13:19 +0900)]
zbd: remove dependency on zone type during i/o

Two different type of zones have a write pointer: Sequential Write
Required (SWR) and Sequential Write Preferred (SWP). Introduce the
zone flag "has_wp" in struct zbd_zone_info and set it to 1 for these
zone types upon initialization, thus avoiding the necessity to check
multiple zone types in core zbd code. This flag replaces zbd_zone_swr()
function and lays the groundwork for supporting additional write
pointer zone types in the future.

The overall functionality stays the same after this commit.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: engines/libzbc: don't fail on assert for offline zones
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:12 +0000 (13:19 +0900)]
zbd: engines/libzbc: don't fail on assert for offline zones

If fio is run against a zoned device that has any zones in OFFLINE
condition, the following assertion is raised -

fio: zbd.c:473: parse_zone_info: Assertion `z->wp <= z->start + zone_size' failed.

This happens because offline zones have no valid write pointer and
it is reported by libzbc and blkzoned as (uint64_t)(-1). To avoid
violating this assertion, set the write pointer in all offline zones
to point at the start of the zone.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: introduce zone_unlock()
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:11 +0000 (13:19 +0900)]
zbd: introduce zone_unlock()

ZBD code already defines a helper function to lock a device zone,
zone_lock(). There is no zone_unlock() function though.

Wrap zone mutex unlock to zone_unlock() helper along with an assert
to make sure that the unlock is successful, i.e. that the function
is being called with the pointer to a locked zone.

Suggested-by: Niklas Cassel <>
Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: add get_zone() helper function
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:10 +0000 (13:19 +0900)]
zbd: add get_zone() helper function

The following pattern is used very widely in zbd.c -

zone = &f->zbd_info->zone_info[zone_idx] .

For the sake of code clarity, wrap this construct into an inline
helper. No change in functionality.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: use zbd_zone_nr() more actively in the code
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:09 +0000 (13:19 +0900)]
zbd: use zbd_zone_nr() more actively in the code

The function zbd_zone_nr() is always called with the first argument
being f->zbd_info. If "f" is made the first argument instead, calls
of this function become more compact end easier to read.

Besides this change, convert several places in the code where the same
zone number calculation is open coded to zbd_zone_nr() calls.
This is a refactoring patch, no change in functionality.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
4 weeks agozbd: return ENOMEM if zone buffer allocation fails
Dmitry Fomichev [Wed, 27 Jan 2021 04:19:08 +0000 (13:19 +0900)]
zbd: return ENOMEM if zone buffer allocation fails

parse_zone_info() function tries to allocate a buffer of
ZBD_REPORT_MAX_ZONES zone descriptors and exits if this allocation
fails. The problem is that it returns 0 error code in this case and
the caller may interpret this as the success.

Just return ENOMEM if we can't allocate that buffer.

Signed-off-by: Dmitry Fomichev <>
Reviewed-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
5 weeks agoMerge branch 'fio-fix-detecting-libpmem' of
Jens Axboe [Wed, 27 Jan 2021 16:51:01 +0000 (09:51 -0700)]
Merge branch 'fio-fix-detecting-libpmem' of

* 'fio-fix-detecting-libpmem' of
  fio: fix detecting libpmem

5 weeks agofio: fix detecting libpmem
Lukasz Dorau [Wed, 27 Jan 2021 07:27:53 +0000 (08:27 +0100)]
fio: fix detecting libpmem

The current test for libpmem in 'configure' fails
in the following way:

$ gcc test.c -lpmem
test.c: In function ‘main’:
test.c:6:27: warning: passing argument 2 of ‘pmem_is_pmem’ \
             makes integer from pointer \
             without a cast [-Wint-conversion]
    6 |   rc = pmem_is_pmem(NULL, NULL);
      |                           ^~~~
      |                           |
      |                           void *
In file included from test.c:1:
/usr/include/libpmem.h:92:43: note: expected ‘size_t’ \
             {aka ‘long unsigned int’} but argument \
             is of type ‘void *’
   92 | int pmem_is_pmem(const void *addr, size_t len);
      |                                    ~~~~~~~^~~

Fix it.

5 weeks agoCalculate min_rate with the consideration of thinktime
Hongwei Qin [Mon, 25 Jan 2021 12:40:00 +0000 (20:40 +0800)]
Calculate min_rate with the consideration of thinktime

This patch updates the compare time if handle_thinktime
sleeps or spin.

Signed-off-by: Hongwei Qin <>
Signed-off-by: Jens Axboe <>
5 weeks agoAdd thinktime_blocks_type parameter
Hongwei Qin [Mon, 25 Jan 2021 12:39:59 +0000 (20:39 +0800)]
Add thinktime_blocks_type parameter

This patch adds a new parameter thinktime_blocks_type to control the
behavior of thinktime_blocks. It can be either `complete` or `issue`. If
it is `complete` (default), fio triggers thinktime when thinktime_blocks
number of blocks are **completed**. If it is `issue`, fio triggers
thinktime when thinktime_blocks number of blocks are **issued**





Current HEAD:
fio jobfile1:
write: IOPS=5, BW=24.6kB/s (24.0KiB/s)(98.3kB/4002msec); 0 zone resets
11 reqs -- 2s -- 8 reqs -- 2s -- 5 reqs -- end

This patch:
fio jobfile1:
write: IOPS=5, BW=24.6kB/s (24.0KiB/s)(98.3kB/4001msec); 0 zone resets
11 reqs -- 2s -- 8 reqs -- 2s -- 5 reqs -- end

fio jobfile2:
write: IOPS=1, BW=8190B/s (8190B/s)(98.3kB/12002msec); 0 zone resets
4 reqs -- 2s -- 4 reqs ... -- 4 reqs -- 2s -- end

fio --server=,8765
Client (On the same machine):
fio --client=,8765 jobfile1
write: IOPS=5, BW=24.6kB/s (24.0KiB/s)(98.3kB/4001msec); 0 zone resets
11 reqs -- 2s -- 8 reqs -- 2s -- 5 reqs -- end

fio --client=,8765 jobfile2
write: IOPS=1, BW=8191B/s (8191B/s)(98.3kB/12001msec); 0 zone resets
4 reqs -- 2s -- 4 reqs ... -- 4 reqs -- 2s -- end

Signed-off-by: Hongwei Qin <>
[axboe: fold patch 3 into this one]
Signed-off-by: Jens Axboe <>
5 weeks agoHOWTO: add sg 'hipri' option
Jens Axboe [Mon, 25 Jan 2021 21:06:48 +0000 (14:06 -0700)]
HOWTO: add sg 'hipri' option

Signed-off-by: Jens Axboe <>
5 weeks agofio: add hipri option to sg engine
Douglas Gilbert [Mon, 25 Jan 2021 20:26:51 +0000 (15:26 -0500)]
fio: add hipri option to sg engine

Adds hipri option to the Linux sg driver engine. This turns on the
SGV4_FLAG_HIPRI flag in recent sg drivers (January 2021) on READ
and WRITE commands (and not on UNMAP (trim), VERIFY, etc). Uses
blk_poll() and the mq_poll() callback in SCSI LLDs. The mechanism
is also called "iopoll".

The Linux sg engine in fio uses the struct sg_io_hdr based interface
known as the sg driver "v3" interface.
Linux sg drivers in the kernel prior to January 2021 (sg version
4.0.12) will just ignore the SGV4_FLAG_HIPRI flag and do normal
completions where LLDs indicate command completion with a (software)
interrupt or similar mechanism.

Update fio.1 (manpage) with new hipri sg engine option.

Signed-off-by: Douglas Gilbert <>
Signed-off-by: Jens Axboe <>
5 weeks agofio: fix dlopen refcounting of dynamic engines
Eric Sandeen [Mon, 25 Jan 2021 19:23:48 +0000 (13:23 -0600)]
fio: fix dlopen refcounting of dynamic engines

ioengine_load() will dlclose the dynamic library if it matches one
that we've already got open, but this defeats the built-in refcounting
done by dlopen/dlclose.  As each thread exits, it calls free_ioengine(),
and this may do a final dlclose on a dynamic ioengine that is still
in use if we don't have the proper reference count.

Fix this by dropping the explicit dlclose of a "matching" dlopened
dynamic engine library, and let each dlclose decrement the refcount
on the engine library as is normal.

This also adds/modifies a couple of debug messages to help track this.

Signed-off-by: Eric Sandeen <>
Signed-off-by: Jens Axboe <>
5 weeks agofio: move dynamic library handle to io_ops structure
Eric Sandeen [Mon, 25 Jan 2021 19:18:31 +0000 (13:18 -0600)]
fio: move dynamic library handle to io_ops structure

Keeping a dynamic engine's dlopen'd dlhandle on a thread structure doesn't
make sense; that thread may exit while others are still using the engine.

Move the dlhandle onto the ops structure itself.

We still only call dlopen for the first thead, which leaves a refcounting
issue which will be fixed in the next patch.

Signed-off-by: Eric Sandeen <>
Signed-off-by: Jens Axboe <>
5 weeks agoMerge branch 'esx-timerfd-bypass' of
Jens Axboe [Sat, 23 Jan 2021 18:04:54 +0000 (11:04 -0700)]
Merge branch 'esx-timerfd-bypass' of

* 'esx-timerfd-bypass' of
  configure: ESX does not have timerfd support

5 weeks agoconfigure: ESX does not have timerfd support
Brian 'Redbeard' Harrington [Fri, 22 Jan 2021 03:10:48 +0000 (19:10 -0800)]
configure: ESX does not have timerfd support

Running fio on an ESX host fails due to the lack of support for file
descriptor based notifications of timer expiration.  This change
bypasses patch 696378af added to increase timer accuracy.

Signed-off-by: Brian 'Redbeard' Harrington <>
6 weeks agoMerge branch 'fix_filename_overrun' of
Jens Axboe [Sat, 16 Jan 2021 20:36:27 +0000 (13:36 -0700)]
Merge branch 'fix_filename_overrun' of

* 'fix_filename_overrun' of
  options: fix buffer overrun

6 weeks agoFix a rate limit issue.
HongweiQin [Sat, 16 Jan 2021 19:52:34 +0000 (03:52 +0800)]
Fix a rate limit issue.

In the current implementation, should_check_rate() returns false
if ddir_rw_sum(td->bytes_done)==0. Therefore, a thread may violate
the rate if iodepth*bs > rate.

This patch addresses the issue by not checking td->bytes_done in should_check_rate.

An example of the issue:

[root@localhost test]# cat fio_randwrite


[root@localhost test]# fio fio_randwrite

blktrace output:
259,1   11        1     0.100550729  6135  Q  WS 3541608 + 8 [fio]
259,1   11        2     0.100552183  6135  G  WS 3541608 + 8 [fio]
259,1   11        3     0.100560373  6135  D  WS 3541608 + 8 [fio]
259,1   11        4     0.100570436  6135  C  WS 3541608 + 8 [0]
259,1   11        5     0.100599816  6135  Q  WS 43470024 + 8 [fio]
259,1   11        6     0.100600513  6135  G  WS 43470024 + 8 [fio]
259,1   11        7     0.100601579  6135  D  WS 43470024 + 8 [fio]
259,1   11        8     0.100612750  6135  C  WS 43470024 + 8 [0]
259,1   11        9     3.101034407  6135  Q  WS 49511928 + 8 [fio]
259,1   11       10     3.101036067  6135  G  WS 49511928 + 8 [fio]
259,1   11       11     3.101054487  6135  D  WS 49511928 + 8 [fio]
259,1   11       12     3.101068699  6135  C  WS 49511928 + 8 [0]
259,1   11       13     6.101267480  6135  Q  WS 27599368 + 8 [fio]
259,1   11       14     6.101269216  6135  G  WS 27599368 + 8 [fio]
259,1   11       15     6.101277050  6135  D  WS 27599368 + 8 [fio]
259,1   11       16     6.101287956  6135  C  WS 27599368 + 8 [0]

Signed-off-by: HongweiQin <>
Signed-off-by: Jens Axboe <>
6 weeks agooptions: fix buffer overrun
Sitsofe Wheeler [Sat, 16 Jan 2021 10:41:02 +0000 (10:41 +0000)]
options: fix buffer overrun

Google's OSS-fuzz turned up a buffer overrun with value of the filename
option due to an overrun in a MAX_PATH sized buffer. To reproduce
compile fio with address sanitizer options like the following

LDFLAGS="-fsanitize=address" ./configure --disable-optimizations \

The issue is demonstrated by the following job:

% COUNT=$(getconf PATH_MAX /); printf "[t]\nfilename=%${COUNT}s" \
  | sed 's/ /@/g' | fio --parse-only -
==45748==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffee8e35780 at pc 0x00010735a343 bp 0x7ffee8e35270 sp 0x7ffee8e34a08
WRITE of size 1025 at 0x7ffee8e35780 thread T0
    #0 0x10735a342 in wrap_vsprintf (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x22342)
    #1 0x10735a9ac in wrap_sprintf (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x229ac)
    #2 0x106e83b01 in add_file filesetup.c:1656
    #3 0x106ee8c87 in str_filename_cb options.c:1320
    #4 0x106ee1b44 in __handle_option parse.c:792
    #5 0x106ed99ad in handle_option parse.c:1014
    #6 0x106eda07d in parse_option parse.c:1184
    #7 0x106ef10ea in fio_options_parse options.c:5199
    #8 0x106e27684 in __parse_jobs_ini init.c:2076
    #9 0x106e25377 in parse_jobs_ini init.c:2127
    #10 0x106e2c971 in parse_options init.c:2989
    #11 0x106ffc884 in main fio.c:42
    #12 0x7fff702f1cc8 in start (libdyld.dylib:x86_64+0x1acc8)

Address 0x7ffee8e35780 is located in stack of thread T0 at offset 1056 in frame
    #0 0x106e836ef in add_file filesetup.c:1644

  This frame has 1 object(s):
    [32, 1056) 'file_name' (line 1646) <== Memory access at offset 1056 overflows this variable

Return an error message to the user by doing the following:

- Allow "regular" string options to have a maxlen parameter
- Set the filename option to have a maxlen of MAX_PATH

Signed-off-by: Sitsofe Wheeler <>
6 weeks agoMerge branch 'fix_keyword_sub' of
Jens Axboe [Sat, 16 Jan 2021 03:52:57 +0000 (20:52 -0700)]
Merge branch 'fix_keyword_sub' of

* 'fix_keyword_sub' of
  options: fix keyword substitution heap overrun

6 weeks agooptions: fix keyword substitution heap overrun
Sitsofe Wheeler [Fri, 15 Jan 2021 20:54:02 +0000 (20:54 +0000)]
options: fix keyword substitution heap overrun

Google's OSS-fuzz turned up a heap overrun when substituting keywords in
job files. To reproduce compile fio with address sanitizer options like
the following

LDFLAGS="-fsanitize=address" ./configure --disable-optimizations \

The issue is demonstrated by the following job:

% printf '[t]\ndescription=$ncpus_' | fio --parse-only -
opt = 'description=$ncpus'
==22547==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000001863 at pc 0x000107a833c9 bp 0x7ffee82ac260 sp 0x7ffee82ac258
READ of size 1 at 0x603000001863 thread T0
    #0 0x107a833c8 in fio_keyword_replace options.c:5124
    #1 0x107a7c6ab in dup_and_sub_options options.c:5158
    #2 0x107a7bb4f in fio_options_parse options.c:5203
    #3 0x1079b2214 in __parse_jobs_ini init.c:2076
    #4 0x1079aff07 in parse_jobs_ini init.c:2127
    #5 0x1079b7501 in parse_options init.c:2989
    #6 0x107b876a4 in main fio.c:42
    #7 0x7fff702f1cc8 in start (libdyld.dylib:x86_64+0x1acc8)

Fix the thinko (because opt is pointing to a later position) and
rearrange some code to make it clearer that olen is being used as an
initial offset

Signed-off-by: Sitsofe Wheeler <>
7 weeks agoMerge branch 'zipf-pareto-lock' of
Jens Axboe [Tue, 12 Jan 2021 17:52:54 +0000 (10:52 -0700)]
Merge branch 'zipf-pareto-lock' of

* 'zipf-pareto-lock' of
  distibutions: Extend flexibility of non-uniform random distributions

7 weeks agoMerge branch 'osx_fix' of
Jens Axboe [Tue, 12 Jan 2021 17:52:25 +0000 (10:52 -0700)]
Merge branch 'osx_fix' of

* 'osx_fix' of
  configure: fix compilation on recent macOS Xcode versions

7 weeks agoMerge branch 'fuzz' of
Jens Axboe [Tue, 12 Jan 2021 17:52:01 +0000 (10:52 -0700)]
Merge branch 'fuzz' of

* 'fuzz' of
  options: Fix buffer over read in fio_keyword_replace
  fuzz: Adds fuzz target for parse_jobs_ini

7 weeks agodistibutions: Extend flexibility of non-uniform random distributions
Adam Kupczyk [Tue, 29 Dec 2020 12:17:17 +0000 (13:17 +0100)]
distibutions: Extend flexibility of non-uniform random distributions

This change affects options random_distribution and file_service_type.
For pareto, zipf and gauss distribution a contept of `center` is implemented.
It allows to fix in place a value that is most probable to access.
fio --randseed=1 --ioengine=libaio --rw=randwrite --nrfiles=16 --bs=4k \
    --size=256m --allow_file_create=1 --write_iolog=log.txt \
    --file_service_type=gauss:10:0.1 --filename_format=object.\$filenum --name=x

cat log.txt |grep write |cut -f 1 -d " " |sort |uniq -c | sort -n | \
sed "s/[.]/ /" | while read a b c; do echo $c $b $a; done |sort -n
0 object 13429
1 object 17928
2 object 14724
3 object 7845
4 object 2476
5 object 468
6 object 44
7 object 3
12 object 24
13 object 318
14 object 1795
15 object 6482

Signed-off-by: Adam Kupczyk <>
7 weeks agooptions: Fix buffer over read in fio_keyword_replace
Philippe Antoine [Tue, 5 Jan 2021 12:00:13 +0000 (13:00 +0100)]
options: Fix buffer over read in fio_keyword_replace

By making sure allocated memory is filled with zeroes

Signed-off-by: Philippe Antoine <>
7 weeks agofuzz: Adds fuzz target for parse_jobs_ini
Philippe Antoine [Tue, 5 Jan 2021 11:59:46 +0000 (12:59 +0100)]
fuzz: Adds fuzz target for parse_jobs_ini

And build it

Signed-off-by: Philippe Antoine <>
7 weeks agoMerge branch 'num2str-patch' of
Jens Axboe [Sat, 9 Jan 2021 22:28:44 +0000 (15:28 -0700)]
Merge branch 'num2str-patch' of

* 'num2str-patch' of
  num2str: fix precision loss bug when the fractional part is close to 1

7 weeks agoMerge branch 'cpu-engine' of
Jens Axboe [Fri, 8 Jan 2021 03:53:00 +0000 (20:53 -0700)]
Merge branch 'cpu-engine' of

* 'cpu-engine' of
  engines/cpu: Fix td_vmsg() call

7 weeks agoengines/cpu: Fix td_vmsg() call
Bart Van Assche [Fri, 8 Jan 2021 03:03:45 +0000 (19:03 -0800)]
engines/cpu: Fix td_vmsg() call

Make sure that the third td_vmsg() argument is a fully expanded string and
also that the fourth argument is a string argument. This was detected by

Fixes: b213922390fe ("engines/cpu: style cleanups")
Signed-off-by: Bart Van Assche <>
8 weeks agoengines/cpu: style cleanups
Jens Axboe [Thu, 7 Jan 2021 23:51:18 +0000 (16:51 -0700)]
engines/cpu: style cleanups

Signed-off-by: Jens Axboe <>
8 weeks agoMerge branch 'evelu-qsort' of
Jens Axboe [Thu, 7 Jan 2021 23:46:32 +0000 (16:46 -0700)]
Merge branch 'evelu-qsort' of

* 'evelu-qsort' of
  engines/cpu: Adding qsort capabilities

8 weeks agoengines/cpu: Adding qsort capabilities
Erwan Velu [Wed, 6 Jan 2021 23:34:06 +0000 (00:34 +0100)]
engines/cpu: Adding qsort capabilities

This commit adds cpumode option into the cpuio engine.
By default, cpumode=noop to keep the current behavior.

If cpumode is set to qsort, fio will use a qsort algorithm
instead of the noop instructions to load the processor.
This mode will consume more cpu power and will be useful to
increase the pressure on the thermal and electrical components.

The expected cpu load is selected as per noop via the cpuload option.
qsort() consumes a lot of energy so the duration
of every loop will vary over time as the power management & cpu clock
changes. To ensure a proper calibration, the thinktime is adjusted after every
qsort() computation to be as precise as possible.

To give an order of magnitude, on an AMD 7502P (TDP=180W) :
cpuload=30, numjobs=64: packagewatt = 134W
cpuload=50, numjobs=64: packagewatt = 167W
cpuload=70, numjobs=64: packagewatt = 180W

The example file is updated to reflect this new capabilities.

The qsort code is coming from stress-qsort.c from stress-ng tool.
This software is also GPLv2 but author was informed and agreed with this usage.

Signed-off-by: Erwan Velu <>
8 weeks agoChange ARRAY_SIZE to FIO_ARRAY_SIZE
Jens Axboe [Wed, 6 Jan 2021 18:32:59 +0000 (11:32 -0700)]

Ensures that we don't clash with external symbols/macros.

Signed-off-by: Jens Axboe <>
8 weeks agoMerge branch 'drop_xp' of
Jens Axboe [Wed, 6 Jan 2021 14:29:48 +0000 (07:29 -0700)]
Merge branch 'drop_xp' of

* 'drop_xp' of
  windows: drop XP support

8 weeks agolog: only compile log_prevalist() if FIO_INC_DEBUG is set
Jens Axboe [Tue, 5 Jan 2021 20:14:28 +0000 (13:14 -0700)]
log: only compile log_prevalist() if FIO_INC_DEBUG is set

Only used for that case.

Signed-off-by: Jens Axboe <>
2 months agoMerge branch 'fix-get-next-file' of
Jens Axboe [Tue, 29 Dec 2020 23:36:32 +0000 (16:36 -0700)]
Merge branch 'fix-get-next-file' of

* 'fix-get-next-file' of
  io_u: Fix bad interaction with --openfiles and non-sequential file selection policy

2 months agoio_u: Fix bad interaction with --openfiles and non-sequential file selection policy
Adam Kupczyk [Mon, 28 Dec 2020 13:55:17 +0000 (14:55 +0100)]
io_u: Fix bad interaction with --openfiles and non-sequential file selection policy

Problem happens when --openfiles is set and file_service_type != FIO_FSERVICE_SEQ.
In function __get_next_file, we decrement file_service_left and if 0, we select
next file to operate on.
However, get_next_file_rand can return -EBUSY if too many files are already opened,
and __get_next_file exits with error.

In next invocation of __get_next_file, we decrement file_service_left again (from 0),
wrapping around to 2^32-1, effectively locking __get_next_file to always select the same.

Algorithm to observe bad behavior:
fio --randseed=1 --ioengine=libaio --rw=randwrite --nrfiles=256 --bs=4k --size=256m \
--loops=50 --allow_file_create=1 --write_iolog=log.txt --file_service_type=normal:20 \
--filename_format=object.\$filenum --name=x --openfiles=100

cat log.txt |grep write |cut -f 1 -d " " |sort |uniq -c | sort -n | sed "s/[.]/ /" \
| while read a b c; do echo $c $b $a; done |sort -n
70 object 17
71 object 19
72 object 22
73 object 65296
74 object 65255
75 object 33
76 object 27
77 object 25
78 object 65243
79 object 36
80 object 49
81 object 47

Signed-off-by: Adam Kupczyk <>
2 months agoconfigure: fix compilation on recent macOS Xcode versions
Sitsofe Wheeler [Wed, 23 Dec 2020 11:58:02 +0000 (11:58 +0000)]
configure: fix compilation on recent macOS Xcode versions

Back in ccf2d89d39b21bc8c7b497b40be5b82eadb80863 ("configure: try to
disable weak linking on OSX") disabling weak symbols was done to prevent
depending on features when building on a newer macOS but targeting an
older one. Fast-forward to Xcode 11.4 and it turns out Apple have broken
this by depending on weak symbols for critical symbols like FD_SET
leading to compilation errors like the following

ld: weak import of symbol '___darwin_check_fd_set_overflow' not supported because of option: -no_weak_imports for architecture x86_64

Other people/projects have been hit by this issue:

but Apple have kept this behaviour into XCode 12 so we should adapt.

- Introduce the concept of configure only CFLAGS
- Switch to using -Werror=partial-availability with the above
- Stop logging a message about disabling weak linking

The above should avoid finding features the target platform doesn't have
while allowing weak linking. The name CONFIGURE_CFLAGS is used to remain
similar to QEMU's configure. Fingers crossed this approach stays
supported by Apple...


Signed-off-by: Sitsofe Wheeler <>
2 months agowindows: drop XP support
Sitsofe Wheeler [Wed, 23 Dec 2020 16:01:52 +0000 (16:01 +0000)]
windows: drop XP support

Windows 2003 has been EOL since 2015 and Windows XP has been EOL since
2014. Technically fio hasn't been properly targetting XP anyway - (see
16d40a15783f9181d64082fc00a970dff485798f 'configure: be explicit about
"XP" Windows API version').

- Strip out support for XP and change the documentation to no longer
  mention it
- Stop targetting XP in the CI 32 bit build

Next stop, Windows 7...

Signed-off-by: Sitsofe Wheeler <>
2 months agoMerge branch 'terse_units' of
Jens Axboe [Thu, 24 Dec 2020 14:38:18 +0000 (07:38 -0700)]
Merge branch 'terse_units' of

* 'terse_units' of
  docs: add missing units to terse headings

2 months agodocs: add missing units to terse headings
Sitsofe Wheeler [Wed, 23 Dec 2020 07:00:02 +0000 (07:00 +0000)]
docs: add missing units to terse headings

In terse output many latency and bandwidth values have non-obvious
units. In the documentation of the format add a microsecond suffix to
latency values and a kb suffix to bandwidth values to clarify things.

Signed-off-by: Sitsofe Wheeler <>
2 months agonum2str: fix precision loss bug when the fractional part is close to 1
gloit042 [Sun, 20 Dec 2020 16:35:21 +0000 (00:35 +0800)]
num2str: fix precision loss bug when the fractional part is close to 1

The result of num2str(11999999999999, 4, 1, 0, N2S_NONE) should
be "12.0G", but current result is "11.0G".

Signed-off-by: Jiahao Li <>
2 months agoMerge branch 'github_issue' of
Jens Axboe [Thu, 17 Dec 2020 23:09:54 +0000 (16:09 -0700)]
Merge branch 'github_issue' of

* 'github_issue' of
  docs: add new section to REPORTING-BUGS and github issue templates

2 months agodocs: add new section to REPORTING-BUGS and github issue templates
Sitsofe Wheeler [Fri, 17 Feb 2017 07:09:12 +0000 (07:09 +0000)]
docs: add new section to REPORTING-BUGS and github issue templates

- Add a section to REPORTING-BUGS to clarify what is required for a good
  GitHub issue
- Add a note to REPORTING-BUGS that questions should go to the mailing
- Add a bug GitHub issue template that encourages people to read
  REPORTING-BUGS and include necessary information
- Add a GitHub issue enhancement template to try and set expectations
- Add a file because GitHub seems to link to it when a
  reporter first makes an issue

Signed-off-by: Sitsofe Wheeler <>
2 months agoMerge branch 'evelu-examples' of
Jens Axboe [Thu, 17 Dec 2020 15:51:38 +0000 (08:51 -0700)]
Merge branch 'evelu-examples' of

* 'evelu-examples' of
  examples: Clarify group_reporting usage
  examples: Clarify thread usage
  examples: Clarify time_based usage
  examples/fsx: Removing deprecated rwmixcycle options

2 months agoexamples: Clarify group_reporting usage
Erwan Velu [Wed, 16 Dec 2020 20:58:34 +0000 (21:58 +0100)]
examples: Clarify group_reporting usage

When reading examples, many jobs assign a value to group_reporting.
No value is expected, so let's have all examples using the same syntax.

Signed-off-by: Erwan Velu <>
2 months agoexamples: Clarify thread usage
Erwan Velu [Wed, 16 Dec 2020 20:48:43 +0000 (21:48 +0100)]
examples: Clarify thread usage

When reading examples, many jobs assign a value to thread.
No value is expected, so let's have all examples using the same syntax.

Signed-off-by: Erwan Velu <>
2 months agoexamples: Clarify time_based usage
Erwan Velu [Wed, 16 Dec 2020 20:42:36 +0000 (21:42 +0100)]
examples: Clarify time_based usage

When reading examples, many jobs assign a value to time_based.
It could even very misleading as some put the same value as for the runtime.
No value is expected, so let's have all examples using the same syntax.

Signed-off-by: Erwan Velu <>
2 months agoexamples/fsx: Removing deprecated rwmixcycle options
Erwan Velu [Wed, 16 Dec 2020 20:27:02 +0000 (21:27 +0100)]
examples/fsx: Removing deprecated rwmixcycle options

Let's remove deprecated option to avoid confusion if some reads it.

Signed-off-by: Erwan Velu <>
2 months agoMerge branch 'wip-rbd-engine-tweaks' of
Jens Axboe [Tue, 15 Dec 2020 16:18:28 +0000 (09:18 -0700)]
Merge branch 'wip-rbd-engine-tweaks' of

* 'wip-rbd-engine-tweaks' of
  engines/rbd: issue initial flush to enable writeback/around mode
  engines/rbd: add support for "direct=1" option

2 months agoflow: fix hang with flow control and zoned block devices
Aravind Ramesh [Mon, 7 Dec 2020 10:30:45 +0000 (10:30 +0000)]
flow: fix hang with flow control and zoned block devices

When flow control is specified between 2 or more threads executing a workload
with zonemode=zbd and flow_sleep is not specified by the user (default to zero),
then a job A can lock a zone Z with the flow ratio exceeded, resulting in the
job to not issue the IO until other jobs IOs balance the flow ratio.
Since job A will wait with the Zone Z locked, other jobs will deadlock waiting
for this zone lock if their workload resulted in this zone Z being chosen
as an IO target.

Executing io_u_quiesce() when the flow ratio is exceeded solves this potential
deadlock as job A will wait for the flow ratio to balance without holding the
zone A lock. To preserve the behavior for regular block devices and to avoid
extra overhead, io_u_quiesce() only needs to be executed when the workload
specifies zonedmode=zbd.

Signed-off-by: Aravind Ramesh <>
Signed-off-by: Shin'ichiro Kawasaki <>
Signed-off-by: Jens Axboe <>
2 months agoMerge branch 'reword-toolarge' of
Jens Axboe [Mon, 7 Dec 2020 23:47:00 +0000 (16:47 -0700)]
Merge branch 'reword-toolarge' of

* 'reword-toolarge' of
  filesetup: reword block size too large message

2 months agofilesetup: reword block size too large message
Sitsofe Wheeler [Sat, 5 Dec 2020 12:12:16 +0000 (12:12 +0000)]
filesetup: reword block size too large message


Signed-off-by: Sitsofe Wheeler <>
2 months agoMerge branch 'cufile' of
Jens Axboe [Sat, 5 Dec 2020 21:45:16 +0000 (14:45 -0700)]
Merge branch 'cufile' of

* 'cufile' of
  ioengine: Add libcufile I/O engine

2 months agoioengine: Add libcufile I/O engine
Brian T. Smith [Tue, 3 Nov 2020 23:54:55 +0000 (23:54 +0000)]
ioengine: Add libcufile I/O engine

The libcufile I/O engine uses NVIDIA GPUDirect Storage (GDS) cuFile API to perform
synchronous I/O directly against GPU buffers via nvidia-fs and a GDS-supported

'configure --enable-libcufile' enables the libcufile engine.

CFLAGS must specify the location of CUDA and cuFile headers.
e.g. CFLAGS="-I/usr/local/cuda/include -I/usr/local/cuda/lib64"

LDFLAGS must specify the location of CUDA and cuFile libraries.
e.g. LDFLAGS="-L/usr/local/cuda/lib64"

The paths used in CFLAGS and LDFLAGS depend upon the build host's
CUDA installation.

libcufile adds the following optons: gpu_dev_ids, cuda_io
Usage is documented in HOWTO, fio.1, examples/libcufile-cufile.fio
and examples/libcufile-posix.fio.

Note that enabling verify when cuda_io=cufile necessitates
cudaMemcpy() to populate the GPU buffer on a write and populate the
CPU buffer on a read. The primary goal of GDS is to not copy data
between CPU and GPU buffers.

Signed-off-by: Brian T. Smith <>
2 months agoFio 3.25 fio-3.25
Jens Axboe [Fri, 4 Dec 2020 18:47:42 +0000 (11:47 -0700)]
Fio 3.25

Signed-off-by: Jens Axboe <>
2 months agoMerge branch 'stat-int-creep3' of
Jens Axboe [Thu, 3 Dec 2020 23:09:43 +0000 (16:09 -0700)]
Merge branch 'stat-int-creep3' of

* 'stat-int-creep3' of
  stat: Prevent the BW and IOPS logging interval from creeping up

3 months agoengines/rbd: issue initial flush to enable writeback/around mode
Jason Dillaman [Wed, 2 Dec 2020 19:03:42 +0000 (14:03 -0500)]
engines/rbd: issue initial flush to enable writeback/around mode

By default librbd will use a writethrough cache until it receives
the first flush. Send a no-op flush after opening the image to
ensure writearound (default) or writeback cache modes can be
properly enabled (unlesss direct=1).

Signed-off-by: Jason Dillaman <>
3 months agoengines/rbd: add support for "direct=1" option
Jason Dillaman [Wed, 2 Dec 2020 18:54:58 +0000 (13:54 -0500)]
engines/rbd: add support for "direct=1" option

When direct IO is enabled, the librbd in-memory cache will be
automatically disabled.

Signed-off-by: Jason Dillaman <>