Recent changes (master)

Jens Axboe <[email protected]> Tue, 16 Jun 2026 06:00:01 -0600
Newsgroups org.kernel.vger.fio
Message-ID <[email protected]>
The following changes since commit 19a6a29c6ba25ceb2caa89f1a601cc3a08ab981a:

  engines/io_uring: code style tweak (2026-06-13 06:32:38 -0600)

are available in the Git repository at:

  git://git.kernel.dk/fio.git master

for you to fetch changes up to fb5b6ae8913be8032beb6cbfe0a4772c74d78cb2:

  Merge branch 'pr-speed-up-norandommap-read-bw' of https://github.com/malikoyv/fio (2026-06-15 11:29:22 -0400)

----------------------------------------------------------------
Vincent Fu (1):
      Merge branch 'pr-speed-up-norandommap-read-bw' of https://github.com/malikoyv/fio

Yehor Malikov (2):
      verify: fix verify starvation with norandommap
      iolog: fix io_piece leak on overlapping in-flight writes

 io_u.c   | 20 ++++++++++++++++----
 iolog.c  |  1 +
 verify.c | 18 +++++++++++++-----
 3 files changed, 30 insertions(+), 9 deletions(-)

---

Diff of recent changes:

diff --git a/io_u.c b/io_u.c
index c3327f16..5d704a33 100644
--- a/io_u.c
+++ b/io_u.c
@@ -2167,11 +2167,23 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr,
 		/*
 		 * Remove errored entry from the verification list
 		 */
-		if (io_u->error)
+		if (io_u->error) {
 			unlog_io_piece(td, io_u);
-		else {
-			atomic_store_release(&io_u->ipo->flags,
-					io_u->ipo->flags & ~IP_F_IN_FLIGHT);
+		} else {
+			unsigned int flags = io_u->ipo->flags & ~IP_F_IN_FLIGHT;
+
+			/*
+			 * If the io_piece was evicted from the verification
+			 * tree due to an overlapping write while in-flight,
+			 * it is no longer reachable for verification. Free
+			 * it here to avoid a memory leak.
+			 */
+			if (!(flags & (IP_F_ONRB | IP_F_ONLIST))) {
+				free(io_u->ipo);
+				io_u->ipo = NULL;
+			} else {
+				atomic_store_release(&io_u->ipo->flags, flags);
+			}
 		}
 	}
 
diff --git a/iolog.c b/iolog.c
index df862ea6..36fcad37 100644
--- a/iolog.c
+++ b/iolog.c
@@ -353,6 +353,7 @@ restart:
 				ipo->offset, ipo->len);
 			td->io_hist_len--;
 			rb_erase(parent, &td->io_hist_tree);
+			__ipo->flags &= ~IP_F_ONRB;
 			remove_trim_entry(td, __ipo);
 			if (!(__ipo->flags & IP_F_IN_FLIGHT))
 				free(__ipo);
diff --git a/verify.c b/verify.c
index d8312815..633a9bb2 100644
--- a/verify.c
+++ b/verify.c
@@ -1425,15 +1425,23 @@ int get_next_verify(struct thread_data *td, struct io_u *io_u)
 	if (!RB_EMPTY_ROOT(&td->io_hist_tree)) {
 		struct fio_rb_node *n = rb_first(&td->io_hist_tree);
 
-		ipo = rb_entry(n, struct io_piece, rb_node);
-
 		/*
-		 * Ensure that the associated IO has completed
+		 * Walk the tree to find the first entry whose IO has
+		 * completed. The tree is sorted by offset, so the first
+		 * entry may still be in-flight while later entries are
+		 * already done.
 		 */
-		if (atomic_load_acquire(&ipo->flags) & IP_F_IN_FLIGHT)
+		while (n) {
+			ipo = rb_entry(n, struct io_piece, rb_node);
+			if (!(atomic_load_acquire(&ipo->flags) & IP_F_IN_FLIGHT))
+				break;
+			n = rb_next(n);
+		}
+
+		if (!n)
 			goto nothing;
 
-		rb_erase(n, &td->io_hist_tree);
+		rb_erase(&ipo->rb_node, &td->io_hist_tree);
 		assert(ipo->flags & IP_F_ONRB);
 		ipo->flags &= ~IP_F_ONRB;
 	} else if (!flist_empty(&td->io_hist_list)) {