Conversation
This fixes the offset/size calculation when "offset" > 0. Previously this had:
fmd->mmap_sz = f->io_size;
fmd->mmap_off = 0;
This is correct only when "offset" (ie f->file_offset) = 0. We can fix this by
either keeping the offset at 0, and map the entire file, or by keeping the size
at f->io_size and setting mmap_off = f->file_offset. On 64-bit there isn't much
difference but on 32-bit the second option is better as it maps less memory.
This patch therefore takes the second approach.
Signed-off-by: Geert Jansen <geertj@google.com>
The engine supports a "full" mode where the entire range for a job is mapped, and a "limited" mode that tries to map less memory. This fixes a bug and implements the following simplified logic: - If we are on a 64-bit architecture, or if io_size <= mmap_map_size, then we map the entire io_size region, and re-use for all IO. - Otherwise, we map the range for each individual IOs. Previously, we would fallback to limited mode in case of 32-bit overflow of the job size. That isn't strict enough as we want to stay below mmap_map_size for a single mapping. This fixes that. Also, in limited mode, this code previously tried to map min(io_size, mmap_map_size) bytes, starting at the offset. This could allow a future IO use the same mapping if happens at a higher offset. I think it's better to keep it simple and get the consistent performance of always having one mmap per IO in limited mode. Signed-off-by: Geert Jansen <geertj@google.com>
The patch adds support for sync operations to the fileoperations, ftruncate, and falloc ioengines. Signed-off-by: Sergei Truschev <s.truschev@yadro.com>
* 'mmap-fixes' of https://github.com/geertj/fio: engines/mmap: fix full/limited prep logic engines/mmap: fix logic when "offset" > 0 engines/mmap: support fadvise_hint
gnutls is required newwer version of libnfs, and so we need to check for this. libnfs version 6.0.0 and later added TLS support. Earlier versions like 5.0.x do not require gnutls. Add a version check in the configure script to detect the libnfs version and only add gnutls as a dependency when libnfs >= 6.0.0 is detected. For systems with older libnfs versions, the build will work without requiring gnutls. For systems with libnfs 6.0.0+, gnutls will be properly detected and linked. Generated-by: Claude AI Reviewed-by: Vincent Fu <vincent.fu@samsung.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Extract the long if condition in str_steadystate_cb() into a separate helper function is_valid_steadystate() for better readability and maintainability. Generated-by: Claude AI Reviewed-by: Vincent Fu <vincent.fu@samsung.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Extract the common logic from steadystate_bw_mean() and steadystate_iops_mean() into a helper function steadystate_data_mean() to reduce code duplication and improve maintainability. Generated-by: Claude AI Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Add fio latency steady state support. The implementation calculates
weighted average latency across all I/O directions and supports both
maximum mean deviation and slope-based detection methods.
We bump FIO_SERVER_VER since struct thread_stat has changed.
Tested successfully against NVMe device with debug output confirming
proper latency calculation and steady state evaluation.
Quick demo with the null engine:
fio --name=test --ioengine=null --size=1G --rw=randread --bs=4k --iodepth=64 --steadystate=lat:100us --ss_dur=10s --runtime=120s --time_based=1
test: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=null, iodepth=64
fio-3.41-20-gf2b2e-dirty
Starting 1 process
Jobs: 1 (f=1): [f(1)][100.0%][r=15.6GiB/s][r=4078k IOPS][eta 00m:00s]
test: (groupid=0, jobs=1): err= 0: pid=1207074: Tue Oct 7 11:47:27 2025
read: IOPS=4054k, BW=15.5GiB/s (16.6GB/s)(153GiB/9899msec)
slat (nsec): min=18, max=33347, avg=22.20, stdev=64.49
clat (nsec): min=135, max=42283, avg=152.74, stdev=173.53
lat (nsec): min=156, max=42306, avg=174.94, stdev=185.32
clat percentiles (nsec):
| 1.00th=[ 139], 5.00th=[ 141], 10.00th=[ 141], 20.00th=[ 143],
| 30.00th=[ 143], 40.00th=[ 145], 50.00th=[ 147], 60.00th=[ 153],
| 70.00th=[ 155], 80.00th=[ 157], 90.00th=[ 163], 95.00th=[ 171],
| 99.00th=[ 217], 99.50th=[ 221], 99.90th=[ 239], 99.95th=[ 270],
| 99.99th=[ 2096]
bw ( MiB/s): min=15344, max=15944, per=100.00%, avg=15835.92, stdev=132.94, samples=19
iops : min=3928298, max=4081694, avg=4053996.63, stdev=34033.65, samples=19
lat (nsec) : 250=99.93%, 500=0.06%, 750=0.01%, 1000=0.01%
lat (usec) : 2=0.01%, 4=0.01%, 10=0.01%, 20=0.01%, 50=0.01%
cpu : usr=99.93%, sys=0.03%, ctx=88, majf=0, minf=6
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=40129848,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
steadystate : attained=yes, bw=15.2GiB/s (15.9GB/s), iops=3976k, lat=152nsec, lat mean dev=2.700
Run status group 0 (all jobs):
READ: bw=15.5GiB/s (16.6GB/s), 15.5GiB/s-15.5GiB/s (16.6GB/s-16.6GB/s), io=153GiB (164GB), run=9899-9899msec
Generated-by: Claude AI
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Introduce a mock test framework to validate specific algorithms and calculations in isolation. This allows testing numerical precision, edge cases, and algorithmic correctness without requiring the full FIO infrastructure. Features: - TAP (Test Anything Protocol) output for CI integration - Isolated testing of specific calculations - Clear documentation of test purposes and goals - Simple make target: 'make mock-tests' The first test validates the numerical precision improvements in steady state latency calculations, demonstrating how the framework can catch subtle precision and overflow issues. Structure: - mock-tests/lib/tap.h: TAP output support - mock-tests/tests/: Individual test programs - mock-tests/Makefile: Build system - mock-tests/README.md: Comprehensive documentation This framework complements the existing integration tests by focusing on unit-level validation of critical calculations. Generated-by: Claude AI Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
When fio has issued 884 billion IOs it is still aable to recover per second latencies with less than 0.1% error using a latency value of 13ms. This is evidence that fio's strategy for estimating per second latency for steady state detection works reasonably well. Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
When rate limiting is enabled, do_io() calls usec_for_io() to calculate delays. If the current operation is a sync (DDIR_SYNC), using it as an index into arrays sized DDIR_RWDIR_CNT (such as td->rate_bps) results in an out-of-bounds access. Guard the rate limiting check in do_io() with ddir_rw() to ensure it only applies to READ, WRITE, and TRIM operations. This fixes a UBSAN out-of-bounds error reported in usec_for_io(). Signed-off-by: Florian Mayer <fmayer@google.com>
* 'patch-1' of https://github.com/fmayer/fio: backend: fix OOB access in usec_for_io() with DDIR_SYNC
This commit fixes the build on musl which fails with the following
error:
```
oslib/linux-blkzoned.c: In function 'blkzoned_move_zone_wp':
oslib/linux-blkzoned.c:389:37: error: 'FALLOC_FL_ZERO_RANGE' undeclared (first use in this function)
389 | ret = fallocate(fd, FALLOC_FL_ZERO_RANGE, z->wp, length);
| ^~~~~~~~~~~~~~~~~~~~
oslib/linux-blkzoned.c:389:37: note: each undeclared identifier is reported only once for each function it appears in
make: *** [Makefile:501: oslib/linux-blkzoned.o] Error 1
make: *** Waiting for unfinished jobs....
```
Signed-off-by: Arthur Gautier <arthur.gautier@arista.com>
* 'baloo/push-lxolyxxkxkpv' of https://github.com/baloo/fio: fix musl builds
If fio is run with md_per_io_size but no pi_chk argument, fio_ioring_io_u_init() passes NULL to strstr(), which segfaults. Use the struct ioring_options prchk flags instead, which have already been parsed from pi_chk in parse_prchk_flags(). Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
* 'fix/prchk-segfault' of https://github.com/calebsander/fio: io_uring: don't segfault if pi_chk isn't specified
…m/mcgrof/fio * '20251023-steady-state-add-latency' of https://github.com/mcgrof/fio: mock-tests: assess per second latency recovery fio: add mock test framework for isolated unit testing fio: add latency steady state detection fio: refactor duplicate code in steadystate_*_mean functions fio: refactor steady state validation check configure: conditionally add gnutls for libnfs >= 6.0.0
For the JSON output latency measurements make the units explicit by changing the name of the array to lat_ns. Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
We have been running out of storage on GitHub-hosted runners in our automated tests. Add a 'cleanup' option to delete artifacts of successful tests as we are running. Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
We have been running out of storage space on our GitHub-host runners for our automated tests. Enable the option to delete artifacts for successful tests as we are running. Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
Since `td->client_type` is always non-zero (CLI is 1, GUI is 2), the check `if (td->client_type)` in `init.c` always triggers, causing --write_hist_log to be unusable when ZLIB is not configured for standalone runs. By checking if the fio instance `is_backend`, ZLIB availability will be checked for fio running as server in server/client mode, and the check will be passed for fio running in standalone mode.
* 'master' of https://github.com/alex310110/fio: write_hist_log: do not require ZLIB for non-server instances
Rename in_ramp_time() and ramp_time_over() to in_ramp_period() and ramp_period_over() respectively. We will be adding other not time-based methods for determining whether the load is ramping up so the old names would be confusing. Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20251219134247.14195-1-jack@suse.cz Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
Instead of checking whether ramp_time is specified each time we need to check whether we are in the ramp period, initialize ramp_period_over based on the ramp_time option. This will simplify things more significantly later when ramp up period can be defined in a different way. Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20251219134247.14195-2-jack@suse.cz Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20251219134247.14195-3-jack@suse.cz Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
Instead of evaluating whether ramp up period has finished on each IO submission and completion evaluate it once per second and set appropriate state variable in thread_data. Later when ramp up period end condition will be more complex and would involve stat data from all threads, it would unnecessarily slow down IO. Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20251219134247.14195-4-jack@suse.cz Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
In some cases the ramp up period is not easy to define by amount of time. This is for example a case of buffered writes measurement where we want to start measuring only once dirty throttling kicks in. The time until dirty throttling kicks in depends on dirty limit (easy to figure out) and speed of writes to the page cache (difficult to know in advance). Add option ramp_size which determines the ramp up period by the amount of IO written (either by each job or by each group when group reporting is enabled). Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20251219134247.14195-5-jack@suse.cz Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
Fio had a bug where it would mistakenly account for trim sizes when allocating memory for data buffers when issuing commands from an iolog. Add this test case to catch possible regressions. Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
Add the copyright header to bsg.c and bsg.h, which provide BSG (Block SCSI Generic) support for the io_uring_cmd engine. The files were previously committed without a license header. Signed-off-by: Jungwon Lee <jjung1.lee@samsung.com>
When a forked job process dies from a fatal signal (SIGABRT from a failed assert(), SIGSEGV, OOM kill), reap_threads() logs "fio: pid=..., got signal=..." and records td->sig, but never sets td->error. The reaped: label only counts td->error into exit_value, so the main fio process exits 0 and the job summary prints err= 0 for the crashed job. The WIFEXITED branch right below does propagate a non-zero exit status, so a worker that exits(1) fails the run while a worker that crashes reports success, defeating any automation that checks fio's exit code. Mark an unexpectedly signaled worker as failed by setting td->error (EINTR) next to the existing log_err. SIGTERM and SIGUSR2 stay excluded, matching the log message: fio uses them for orderly termination. Setting td->error rather than bumping exit_value directly keeps the accounting in one place and makes the job summary show a non-zero err for the crashed job. Tested by sending SIGABRT to one worker of a two-job process-based run: the crashed job now reports err= 4 and fio exits 1 (both were 0 before); a crash-free run still reports err= 0 for all jobs and exits 0. Fixes: #2127 Signed-off-by: Vlad Tudose <tudosevt@amazon.com>
* 'add_copyright' of https://github.com/ljw8161/fio: engines/io_uring: add copyright header to bsg files
…tes130272/fio * 'feat/hipfile-upstream-rebase' of https://github.com/sbates130272/fio: examples/doc: add libhipfile example job files and documentation engines/libhipfile: add ROCm hipFile engine engines/gpuaccel: add per-backend sync flags and backend-scoped state engines: refactor libcufile.c into a shared gpuaccel layer
An example job file was accidentally committed to the repository root directory. Move it to the examples directory. Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
fio_ioring_cmd_init() assigns ld->write_opcode = bsg_cmd_write_10 when cmd_type=bsg, but that field is never read on the bsg submission path. fio_bsg_uring_cmd_prep() fills bc->cdb[0] directly from io_u->ddir, and ld->write_opcode is only consumed by fio_nvme_uring_cmd_prep() on the nvme path. The assignment has therefore never had any effect. Drop the dead assignment. The surrounding `if (write_mode == WRITE)` branch existed only to hold it; once the assignment is gone the branch is empty, so the check collapses to a plain rejection of unsupported write modes. Fixes: d77ed2b ("engines/io_uring: Add bsg support for io_uring_cmd engine") Signed-off-by: Jungwon Lee <jjung1.lee@samsung.com>
The bsg completion was being parsed in two places: fio_ioring_cmd_event() decoded the packed SCSI status from cqe->big_cqe[0] into io_u->error, and fio_ioring_cmd_errdetails() re-derived the SCSI status and host status from io_u->error. The NVMe path only does this breakdown once, in errdetails. Drop the bsg-specific decoding from event and store the raw cqe->big_cqe[0] in io_u->error, leaving errdetails as the single place that splits the SCSI status (bits 0-7) and host status (bits 16-23). Fixes: d77ed2b ("engines/io_uring: Add bsg support for io_uring_cmd engine") Signed-off-by: Jungwon Lee <jjung1.lee@samsung.com>
The bsg cmd_type of the io_uring_cmd engine has so far hardcoded READ(10) and WRITE(10) for DDIR_READ and DDIR_WRITE. That caps the supported LBA range at 32 bits and the transfer length at 65535 blocks, which prevents benchmarking devices whose capacity or per-I/O transfer size exceeds those limits, and it also prevents comparing the performance characteristics of different CDB lengths of the same command. Add a new engine option, cdb_len, that selects the SCSI CDB length used for READ/WRITE commands. Supported values are 10, 16, and 32. The 32-byte command is encoded as a variable-length CDB (opcode 0x7F) with the READ(32) and WRITE(32) service actions. The default is 0 (auto): the smallest CDB whose LBA and transfer-length fields can hold the request is chosen, escalating from READ(10)/WRITE(10) to READ(16)/WRITE(16) as the LBA or transfer length grows, mirroring the sg engine. This lets fio drive devices whose capacity or per-I/O size exceeds the 10-byte limits without requiring the user to pick a CDB length up front. The 32-byte CDB shares the same 64-bit LBA and 32-bit length field widths as the 16-byte CDB, so auto-escalation never reaches it and it remains opt-in only (for exercising the variable-length CDB path itself). When an explicit cdb_len is set, requests whose LBA or transfer length would overflow the fields of the selected CDB length are rejected with -EINVAL rather than being silently promoted to a larger CDB. This preserves the user's explicit intent when a specific CDB length is chosen for benchmarking. SYNCHRONIZE CACHE follows cdb_len as well: the 10-byte command (0x35) is issued when cdb_len=10, and the 16-byte command (0x91) is issued otherwise. SBC does not define a 32-byte SYNCHRONIZE CACHE service action, so cdb_len=32 falls back to the 16-byte command. UNMAP has no CDB length selection and keeps its fixed 10-byte CDB regardless of cdb_len. Signed-off-by: Jungwon Lee <jjung1.lee@samsung.com>
The existing write_mode=verify option is currently only handled for the nvme cmd_type. Extend it to the bsg cmd_type so that SCSI VERIFY commands can be used as the write-side operation of a workload. This is useful for measuring the cost of medium verification against the same address range that would otherwise be written. The VERIFY CDB length follows the cdb_len option: VERIFY(10)=0x2F, VERIFY(16)=0x8F, and VERIFY(32) via the variable-length CDB service action. The data comparison behavior is controlled by a new verify_bytchk option that maps to the CDB BYTCHK field: 0 - medium verification only, no host data transfer (SG_DXFER_NONE) 1 - compare the full transfer against the medium byte by byte 3 - compare a single block against every block in the range For BYTCHK 1 and 3 the command sends data to the device (SG_DXFER_TO_DEV); BYTCHK 3 transfers only a single block while the CDB still carries the full block count. verify_bytchk defaults to 0 and is rejected unless write_mode=verify. VERIFY is the first bsg command that issues SG_DXFER_NONE with a non-zero io_u->xfer_buflen (the buflen encodes the block count that the device verifies against the medium). The previous fio_bsg_uring_cmd_init() lumped SG_DXFER_NONE into the else branch that populates din_xferp/din_xfer_len, which happened to be harmless only because DDIR_SYNC's xfer_buflen was zero. Tighten the else to match SG_DXFER_FROM_DEV explicitly so SG_DXFER_NONE leaves the data transfer fields cleared. writefua is rejected when combined with write_mode=verify. The FUA bit is not defined for the VERIFY command in any of the CDB variants that we support, and silently dropping the flag would hide a user misconfiguration. Signed-off-by: Jungwon Lee <jjung1.lee@samsung.com>
Introduce a new engine option, read_mode, that selects which command variant is issued for DDIR_READ, symmetric to the existing write_mode option. Two values are supported: 'read', which preserves the current behavior, and 'prefetch', which issues SCSI PRE-FETCH commands. PRE-FETCH pulls the requested LBAs from the medium into the device read cache without transferring the data to the host. This is useful for warming the device read cache prior to a subsequent measurement, and for measuring the overhead of the prefetch path itself. The PRE-FETCH CDB length follows the cdb_len option: PRE-FETCH(10)=0x34 and PRE-FETCH(16)=0x90. SBC does not define a 32-byte PRE-FETCH service action, so cdb_len=32 is rejected with read_mode=prefetch rather than silently falling back. readfua is also rejected in this mode because the FUA bit is not defined for PRE-FETCH. read_mode is currently only meaningful for the bsg cmd_type. Passing a non-default value with cmd_type=nvme is rejected at engine init rather than silently ignored, so that users notice a misconfiguration. Signed-off-by: Jungwon Lee <jjung1.lee@samsung.com>
Modify configure to only require gnutls on Linux when libnfs is >= 6. Signed-off-by: Kurt Miller <kurt@openbsd.org>
* 'gnutls.configure' of https://github.com/bsdkurt/fio: libnfs only requires gnutls on Linux Modify configure to only require gnutls on Linux when libnfs is >= 6.
* 'bsg-update' of https://github.com/ljw8161/fio: engines/io_uring: add read_mode=prefetch for bsg cmd_type engines/io_uring: support write_mode=verify for bsg cmd_type engines/io_uring: add cdb_len option for bsg cmd_type engines/io_uring: drop bsg status parsing from event engines/io_uring: drop unused write_opcode assignment on bsg path
Add some test cases for newly added cmd_type=bsg features. These include tests for the cdb_len, write_mode=verify, and read_mode=prefetch options. Example invocation: python3 t/io_uring_cmd.py --cmd_type=bsg "--dut=/dev/bsg/6\:0\:0\:0" Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
The flag is RWF_DONTCACHE and not RWF_UNCACHED.[1] [1] https://man7.org/linux/man-pages/man2/pwritev2.2.html Signed-off-by: Pankaj Raghav <p.raghav@samsung.com>
* 'doc-fix' of https://github.com/Panky-codes/fio: doc: change RWF_UNCACHED to RWF_DONTCACHE
…ladyyy/fio * 'reap-signaled-worker-exit-code' of https://github.com/Vladyyy/fio: backend: exit non-zero when a job process is killed by a signal
verify_zero() logs the file, offset and length of a mismatch, but unlike the header and pattern verify paths it never writes out the data it read. That makes trim_verify_zero and write zeroes verify failures harder to analyze than a regular verify failure, where verify_dump=1 leaves the offending block on disk for inspection. Dump the received block from verify_zero() when verify_dump is set, so that both callers benefit. There is no point in also dumping an expected buffer, as the expected contents are all zeroes. Signed-off-by: Sarthak Killedar <sarthak.killedar@gmail.com>
Calling io_ops->commit() will not update io_u_in_flight and io_u_queued accordingly. If iio_u_queued is not reset properly the fio may need to make unnecessary stop to drain the queue. Which may degrade the throughput. Signed-off-by: Dennis Chang <cherhungc@google.com>
* 'verify-zero-dump' of https://github.com/sarthak-k/fio: verify: dump the received buffer when zero verify fails
…nischerchang/fio * 'consolidate_commit_call_path' of https://github.com/dennischerchang/fio: Consolidate all caller of io_ops_commit() to call td_io_commit().
Recent QEMU tests have been failing with errors like this: dpkg: unrecoverable fatal error, aborting: unable to flush /var/lib/dpkg/updates/tmp.i after padding: No space left on device Example: https://github.com/axboe/fio/actions/runs/33871509826/job/101018344984?pr=2133 Fix this by resizing the image. Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
and definition. In stat.c, show_ddir_status() and add_ddir_status_json() calls convert_agg_kbytes_percent() with 'double' parameter however convert_agg_kbytes_percent() defines the parameter as 'int'. Fixes: #2142 Signed-off-by: Dennis Chang chernhungc@google.com
…nt' of https://github.com/dennischerchang/fio * 'inconsistent_parameter_type_in_convert_agg_kbytes_percent' of https://github.com/dennischerchang/fio: Fix convert_agg_kbytes_percent() inconsistent type between caller and definition.
TD_RAMP increments both nr_running and nr_ramp, so nr_ramp is a subset of nr_running and display_thread_status() can compare the two. The TD_SETTING_UP side would increment only nr_setting_up, yet the percentage calculation scales by nr_setting_up / nr_running, a ratio that only means anything if setting up jobs are counted in nr_running as well: the existing ratio can drive the multiplier negative. A job that is setting up is started and doing work, it just has not issued IO yet, so count it in nr_running and treat nr_setting_up as the subset as intended. Today this only covers the brief windows where setup_files() and pre_read_file() bump the state, but it means the status line reports such a job instead of suppressing the whole line. Signed-off-by: Keith Busch <kbusch@kernel.org> Link: https://lore.kernel.org/r/20260910161310.1478081-2-kbusch@meta.com Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
run_threads() moves a job from TD_INITIALIZED straight to TD_RUNNING and only then releases it. The job still has all of its setup left to do: exec_prerun, pre_read_files(), setup_files(), init_io_u(), rate_submit_init() and finally set_epoch_time(). The job claims to be running for that entire window when it has not issued any IO and has no epoch to measure itself against. Anything that reads the state during that window gets a wrong answer. thread_eta() is the most readily observable one: it derives elapsed from td->epoch, which is still zeroed, so a job with a three second exec_prerun reports Jobs: 1 (f=0): [R(1)][-.-%][eta 00m:00s] Jobs: 1 (f=0): [R(1)][50.0%][eta 00m:03s] before doing any work at all. Running, half done and no time left, none of which is true. Promote to TD_SETTING_UP instead, which is what that state is for, and let the job promote itself to TD_RAMP or TD_RUNNING once setup is over and it has recorded its epoch. The same job now reports Jobs: 1 (f=1): [I(1)][0.0%][eta 00m:03s] Widen the TERMINATE_STONEWALL check to match. It tests for runstate >= TD_RUNNING to find jobs worth terminating, and a job in the setup window used to satisfy that. Without this, exit_what=stonewall stops reaching a job that is still setting up, and a test where the short job is reaped while a longer one sits in exec_prerun goes from 5.5s to 20.5s. Note TD_RAMP sorts below TD_SETTING_UP, so ramping jobs remain excluded from that check exactly as before. Signed-off-by: Keith Busch <kbusch@kernel.org> Link: https://lore.kernel.org/r/20260910161310.1478081-3-kbusch@meta.com Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
The ETA of a running job is capped at "timeout + done_secs - elapsed".
done_secs is a global accumulator of the runtime of every job reaped so
far, so the cap grows every time a job finishes. Whenever the cap is
what actually gets reported, the ETA jumps back up by the runtime of
everything that has already completed.
The cap is what gets reported when the progress based estimate exceeds
the remaining runtime, that is when perc is below elapsed/timeout. Any
job that is behind on bytes relative to its runtime is in that state,
so this covers the common "size the job to the whole device, bound it
with runtime" pattern. A job that would complete its size early stays
at or above elapsed/timeout and never reaches the cap.
time_based makes no difference either way. It only lowers perc to
min(perc, elapsed/timeout), so a time_based job that cannot finish its
size within the runtime is affected exactly like a size based one.
It is most visible with stonewalled jobs, where the ETA climbs back to
the full run time at every batch boundary instead of counting down:
fio --name=global --filename=/dev/zero --runtime=5 --size=10T \
--stonewall --name=a --name=b --name=c --name=d --name=e
before: 22 21 20 24 23 22 21 20 24 23 22 21 20 24 ...
after: 22 21 20 19 18 17 16 15 14 13 ... 02 01 00
Shrinking size until the jobs complete it within the runtime makes the
symptom disappear, which is a good way to confirm the cap is what is
being reported.
It is not specific to stonewall. Two concurrent jobs with runtime=5 and
runtime=20 show the same jump when the short one is reaped at t=5.
done_secs made sense when it was introduced: thread_eta() was handed
the global elapsed time back then, so "timeout + done_secs" was this
job's projected finish time relative to the start of the whole run.
b29ee5b switched elapsed to be per job, measured from td->epoch, but
left the done_secs term behind.
A job is terminated once utime_since(&td->epoch, now) reaches
td->o.timeout, so with a per job elapsed the cap is simply
"timeout - elapsed". Use that, and clamp at zero instead of relying on
the unsigned subtraction wrapping.
Fixes: b29ee5b ("Update ramp_time")
Signed-off-by: Keith Busch <kbusch@kernel.org>
Link: https://lore.kernel.org/r/20260910161310.1478081-4-kbusch@meta.com
Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
Capping the ETA at the job's own remaining runtime removed the last reader of done_secs. Drop the variable, along with the gettime call that maintained it on every reap. Signed-off-by: Keith Busch <kbusch@kernel.org> Link: https://lore.kernel.org/r/20260910161310.1478081-5-kbusch@meta.com Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
Various error cases in fio_send_file() might send an uninitialized buffer over the wire. The server should ignore this when errno is set, but it's best practice to not ship heap data over the wire, so fix that by: - using calloc vs malloc in the initial allocation so that early error paths send initialized data. - grow the buffer via realloc only after open() succeeds, so that an open() failure doesn't send a grown/uninit buffer back with the error. Signed-off-by: Eric Sandeen <sandeen@redhat.com> Link: https://patch.msgid.link/20260917205554.2281093-1-sandeen@redhat.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot]
Can you help keep this open source service alive? 💖 Please sponsor : )