Skip to content

Commit 3e3436c

Browse files
author
Vlad Tudose
committed
trimwrite: do not terminate between a trim and its paired write
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>
1 parent c76c61b commit 3e3436c

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

backend.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,17 @@ void on_fsync_completed(struct thread_data *td, struct io_u *io_u)
11501150
*
11511151
* Returns number of bytes written and trimmed.
11521152
*/
1153+
static bool trimwrite_mid_pair(struct thread_data *td)
1154+
{
1155+
struct fio_file *f;
1156+
1157+
if (!td_trimwrite(td) || td->o.nr_files != 1)
1158+
return false;
1159+
1160+
f = td->files[0];
1161+
return f->last_start[DDIR_WRITE] != f->last_start[DDIR_TRIM];
1162+
}
1163+
11531164
static void do_io(struct thread_data *td, uint64_t *bytes_done)
11541165
{
11551166
unsigned int i;
@@ -1211,7 +1222,8 @@ static void do_io(struct thread_data *td, uint64_t *bytes_done)
12111222

12121223
if (runtime_exceeded(td, &td->ts_cache)) {
12131224
__update_ts_cache(td);
1214-
if (runtime_exceeded(td, &td->ts_cache)) {
1225+
if (runtime_exceeded(td, &td->ts_cache) &&
1226+
!trimwrite_mid_pair(td)) {
12151227
fio_mark_td_terminate(td);
12161228
break;
12171229
}
@@ -1228,6 +1240,7 @@ static void do_io(struct thread_data *td, uint64_t *bytes_done)
12281240
*/
12291241
if (bytes_issued >= total_bytes &&
12301242
!td->o.read_iolog_file &&
1243+
!trimwrite_mid_pair(td) &&
12311244
(!td->o.time_based ||
12321245
(td->o.time_based && td->o.verify != VERIFY_NONE)))
12331246
break;

0 commit comments

Comments
 (0)