aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulian Sun <sunjunchao@bytedance.com>2025-09-30 16:53:15 +0800
committerChristian Brauner <brauner@kernel.org>2025-10-20 20:22:39 +0200
commit1888635532fbbd6be4a4368621085c3a197279f8 (patch)
tree4c768f48356bc372075189dcbc5e61f64b8c7460
parent3a8660878839faadb4f1a6dd72c3179c1df56787 (diff)
downloadtip-1888635532fbbd6be4a4368621085c3a197279f8.tar.gz
writeback: Wake up waiting tasks when finishing the writeback of a chunk.
Writing back a large number of pages can take a lots of time. This issue is exacerbated when the underlying device is slow or subject to block layer rate limiting, which in turn triggers unexpected hung task warnings. We can trigger a wake-up once a chunk has been written back and the waiting time for writeback exceeds half of sysctl_hung_task_timeout_secs. This action allows the hung task detector to be aware of the writeback progress, thereby eliminating these unexpected hung task warnings. This patch has passed the xfstests 'check -g quick' test based on ext4, with no additional failures introduced. Signed-off-by: Julian Sun <sunjunchao@bytedance.com> Reviewed-by: Jan Kara <jack@suse.cz> Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
-rw-r--r--fs/fs-writeback.c10
-rw-r--r--include/linux/backing-dev-defs.h1
2 files changed, 10 insertions, 1 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 2b35e80037feed..61a980a06ceeb3 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -14,6 +14,7 @@
* Additions for address_space-based writeback
*/
+#include <linux/sched/sysctl.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/spinlock.h>
@@ -213,7 +214,8 @@ static void wb_queue_work(struct bdi_writeback *wb,
void wb_wait_for_completion(struct wb_completion *done)
{
atomic_dec(&done->cnt); /* put down the initial count */
- wait_event(*done->waitq, !atomic_read(&done->cnt));
+ wait_event(*done->waitq,
+ ({ done->progress_stamp = jiffies; !atomic_read(&done->cnt); }));
}
#ifdef CONFIG_CGROUP_WRITEBACK
@@ -2014,6 +2016,12 @@ static long writeback_sb_inodes(struct super_block *sb,
*/
__writeback_single_inode(inode, &wbc);
+ /* Report progress to inform the hung task detector of the progress. */
+ if (work->done && work->done->progress_stamp &&
+ (jiffies - work->done->progress_stamp) > HZ *
+ sysctl_hung_task_timeout_secs / 2)
+ wake_up_all(work->done->waitq);
+
wbc_detach_inode(&wbc);
work->nr_pages -= write_chunk - wbc.nr_to_write;
wrote = write_chunk - wbc.nr_to_write - wbc.pages_skipped;
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index c5c9d89c73edcc..c8aa749790b14e 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -63,6 +63,7 @@ enum wb_reason {
struct wb_completion {
atomic_t cnt;
wait_queue_head_t *waitq;
+ unsigned long progress_stamp; /* The jiffies when slow progress is detected */
};
#define __WB_COMPLETION_INIT(_waitq) \