Unverified Commit 18886355 authored by Julian Sun's avatar Julian Sun Committed by Christian Brauner
Browse files

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: default avatarJulian Sun <sunjunchao@bytedance.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Suggested-by: default avatarPeter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 3a866087
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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)	\