trimwrite: do not terminate between a trim and its paired write - #2131
trimwrite: do not terminate between a trim and its paired write#2131Vladyyy wants to merge 1 commit into
Conversation
In trimwrite mode each block is trimmed and then written back by two
consecutive io_us, paired via the per-file last_start markers in
set_rw_ddir(). The do_io() termination checks (runtime_exceeded and
the bytes_issued budget) run once per io_u with no awareness of the
pairing, so a time_based or byte-bounded run can stop after issuing a
trim but before its paired write: the final block is left deallocated
("dangling trim") and replay-based verification of the write_iolog
false-fails with "bad magic" on that range. Reproduces on effectively
every time_based trimwrite run.
Defer termination while a pair is open so the loop issues exactly one
more io_u (the paired write) and terminates on the next iteration.
Validated on a loop device: 10/10 time_based runs ended on a dangling
trim (trims == writes+1, iolog replay failing "bad magic") before,
0/10 after with replay passing; loops-bounded runs issue identical op
counts (already pair-complete), so their behavior is unchanged.
Fixes: axboe#2122
Signed-off-by: Vlad Tudose <tudosevt@amazon.com>
2a6b1d4 to
3e3436c
Compare
| */ | ||
| if (bytes_issued >= total_bytes && | ||
| !td->o.read_iolog_file && | ||
| !trimwrite_mid_pair(td) && |
There was a problem hiding this comment.
bytes_issued is adjusted near the top of do_io() for trimwrite workloads. Why is this check necessary here?
| * | ||
| * Returns number of bytes written and trimmed. | ||
| */ | ||
| static bool trimwrite_mid_pair(struct thread_data *td) |
There was a problem hiding this comment.
The comment above this function applies to do_io()
| { | ||
| struct fio_file *f; | ||
|
|
||
| if (!td_trimwrite(td) || td->o.nr_files != 1) |
There was a problem hiding this comment.
td_trimwrite() just checks if the write and trim bits of the job's ddir are set. Both of the bits are set for rw=[rand]trimwrite but can also be set for iolog replay jobs. Would this check cause an iolog replay job that includes trims and writes to exceed its specified runtime?
|
It would help if in addition to the prose descriptions of how to reproduce the bug, you also include specific command lines or job files. |
In trimwrite mode each block is trimmed and then written back by two
consecutive io_us, paired via the per-file last_start markers in
set_rw_ddir(). The do_io() termination checks (runtime_exceeded and
the bytes_issued budget) run once per io_u with no awareness of the
pairing, so a time_based or byte-bounded run can stop after issuing a
trim but before its paired write: the final block is left deallocated
("dangling trim") and replay-based verification of the write_iolog
false-fails with "bad magic" on that range. Reproduces on effectively
every time_based trimwrite run.
Defer termination while a pair is open so the loop issues exactly one
more io_u (the paired write) and terminates on the next iteration.
Validated on a loop device: 10/10 time_based runs ended on a dangling
trim (trims == writes+1, iolog replay failing "bad magic") before,
0/10 after with replay passing; loops-bounded runs issue identical op
counts (already pair-complete), so their behavior is unchanged.
Fixes: #2122
Signed-off-by: Vlad Tudose tudosevt@amazon.com