Recent changes (master)
Jens Axboe <[email protected]> Thu, 2 Apr 2026 06:00:01 -0600
| Newsgroups | org.kernel.vger.fio |
|---|---|
| Message-ID | <[email protected]> |
The following changes since commit 698fa8f0682b809b3f85f50c593067e90108f92e:
Merge branch 'fix-null-comm-prctl' of https://github.com/Criticayon/fio (2026-03-18 19:31:08 -0600)
are available in the Git repository at:
git://git.kernel.dk/fio.git master
for you to fetch changes up to d0218ba66e9dc8402f1ac366b964277a1f2f2797:
Merge branch 'fix_statsem_deadlock' of https://github.com/RyanTedrick/fio (2026-04-01 09:08:08 -0600)
----------------------------------------------------------------
Jens Axboe (1):
Merge branch 'fix_statsem_deadlock' of https://github.com/RyanTedrick/fio
Ryan Tedrick (1):
Fix stat_sem/rusage_sem deadlock during stats collection
backend.c | 9 ++++-----
stat.c | 35 ++++++++++++++++++++++-------------
2 files changed, 26 insertions(+), 18 deletions(-)
---
Diff of recent changes:
diff --git a/backend.c b/backend.c
index c63bbd07..4ce3d07f 100644
--- a/backend.c
+++ b/backend.c
@@ -2095,11 +2095,10 @@ static void *thread_main(void *data)
clear_state = true;
/*
- * Make sure we've successfully updated the rusage stats
- * before waiting on the stat mutex. Otherwise we could have
- * the stat thread holding stat mutex and waiting for
- * the rusage_sem, which would never get upped because
- * this thread is waiting for the stat mutex.
+ * Service any pending rusage request, then acquire stat_sem to update
+ * runtime counters. This trylock loop will primarily guard against
+ * contention from concurrent stat calls or other slow operations under
+ * stat_sem.
*/
deadlock_loop_cnt = 0;
do {
diff --git a/stat.c b/stat.c
index 63c9927f..305d1ae3 100644
--- a/stat.c
+++ b/stat.c
@@ -2821,16 +2821,35 @@ int __show_running_run_stats(void)
unsigned long long *rt;
struct timespec ts;
- fio_sem_down(stat_sem);
-
rt = malloc(thread_number * sizeof(unsigned long long));
fio_gettime(&ts, NULL);
+ /*
+ * Collect rusage from workers outside stat_sem to prevent deadlock caused
+ * by semaphore contention between the stat thread and the worker threads.
+ */
for_each_td(td) {
if (td->runstate >= TD_EXITED)
continue;
- td->update_rusage = 1;
+ if (td->rusage_sem) {
+ td->update_rusage = 1;
+ /* Prevent deadlock if worker exits between first check and sem_down */
+ if (td->runstate >= TD_EXITED) {
+ td->update_rusage = 0;
+ continue;
+ }
+ fio_sem_down(td->rusage_sem);
+ }
+ td->update_rusage = 0;
+ } end_for_each();
+
+ fio_sem_down(stat_sem);
+
+ for_each_td(td) {
+ if (td->runstate >= TD_EXITED)
+ continue;
+
for_each_rw_ddir(ddir) {
td->ts.io_bytes[ddir] = td->io_bytes[ddir];
}
@@ -2845,16 +2864,6 @@ int __show_running_run_stats(void)
td->ts.runtime[DDIR_TRIM] += rt[__td_index];
} end_for_each();
- for_each_td(td) {
- if (td->runstate >= TD_EXITED)
- continue;
- if (td->rusage_sem) {
- td->update_rusage = 1;
- fio_sem_down(td->rusage_sem);
- }
- td->update_rusage = 0;
- } end_for_each();
-
__show_run_stats();
for_each_td(td) {