[PATCH 1/2] verify: fix write tracking in error cases
Shin'ichiro Kawasaki <[email protected]> Sat, 9 Aug 2025 10:15:54 +0900
| Newsgroups | org.kernel.vger.fio |
|---|---|
| Message-ID | <[email protected]> |
Commit a9ba7cef70a7 ("verify: rework write tracking for use with
verify_save_state()") reworked write tracking for verify workloads.
As part of the rework, two new functions were added: log_inflight() and
invalidate_inflight(). log_inflight() is called when a write io_u is
prepared for the verify workload. The call is ensured to occur only once
per write io_u by using the IO_U_F_PATTERN_DONE flag.
invalidate_inflight() is called when the write io_u completes. Under
non-failure conditions, the number of calls to these two functions
is expected to be equal upon the completions of all writes.
However, when a write io_u fails with an error, the balance between the
calls to log_inflight() and invalidate_inflight() breaks for two
reasons. Firstly, invalidate_inflight() is not called when the failed
sync writes. Secondly, the IO_U_F_PATTERN_DONE flag is not cleared when
the failed write io_u is reused. As a result the subsequent attempt to
prepare the io_u does not trigger the call to log_inflight(). The
unbalanced function calls causes mismatch between io_u->numberio and
td->inflight_issued, then results in abort in log_inflight(). This
failure symptom is observed by running t/zbd/run-tests-against-nullb for
the test case 72 in t/zbd/test-zbd-support.
To fix the unbalanced function calls, add calls to log_inflight() in
the sync write failure path in io_queue_event(). This ensures that
failed sync writes are appropriately logged. To fix the left
IO_U_F_PATTERN_DONE flag, clear the flag in io_queue_event() failure
path. Additional, clear the IO_U_F_BUSY_OK flag which is to be cleared
when inflight I/Os complete. For the code simplicity, introduce a new
helper function io_u_clear_inflight_flags() to avoid duplication of
the code to clear the flags.
Fixes: a9ba7cef70a7 ("verify: rework write tracking for use with verify_save_state()")
Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
---
backend.c | 2 ++
io_u.c | 11 +++++++++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/backend.c b/backend.c
index 922309a0..858506c4 100644
--- a/backend.c
+++ b/backend.c
@@ -449,6 +449,7 @@ int io_queue_event(struct thread_data *td, struct io_u *io_u, int *ret,
case FIO_Q_COMPLETED:
if (io_u->error) {
*ret = -io_u->error;
+ invalidate_inflight(td, io_u);
clear_io_u(td, io_u);
} else if (io_u->resid) {
long long bytes = io_u->xfer_buflen - io_u->resid;
@@ -467,6 +468,7 @@ int io_queue_event(struct thread_data *td, struct io_u *io_u, int *ret,
if (!from_verify)
unlog_io_piece(td, io_u);
td_verror(td, EIO, "full resid");
+ invalidate_inflight(td, io_u);
clear_io_u(td, io_u);
break;
}
diff --git a/io_u.c b/io_u.c
index 6d0f32a8..78dbac9c 100644
--- a/io_u.c
+++ b/io_u.c
@@ -869,9 +869,16 @@ void put_io_u(struct thread_data *td, struct io_u *io_u)
__td_io_u_unlock(td);
}
+static inline void io_u_clear_inflight_flags(struct thread_data *td,
+ struct io_u *io_u)
+{
+ io_u_clear(td, io_u, IO_U_F_FLIGHT | IO_U_F_BUSY_OK |
+ IO_U_F_PATTERN_DONE);
+}
+
void clear_io_u(struct thread_data *td, struct io_u *io_u)
{
- io_u_clear(td, io_u, IO_U_F_FLIGHT);
+ io_u_clear_inflight_flags(td, io_u);
put_io_u(td, io_u);
}
@@ -2090,7 +2097,7 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr,
dprint_io_u(io_u, "complete");
assert(io_u->flags & IO_U_F_FLIGHT);
- io_u_clear(td, io_u, IO_U_F_FLIGHT | IO_U_F_BUSY_OK | IO_U_F_PATTERN_DONE);
+ io_u_clear_inflight_flags(td, io_u);
invalidate_inflight(td, io_u);
if (td->o.zone_mode == ZONE_MODE_ZBD && td->o.recover_zbd_write_error &&
--
2.49.0