From 8d04539dddc46d58b510ae9680e769ba45e4b8d0 Mon Sep 17 00:00:00 2001 From: Andrew Morton <akpm@zip.com.au> Date: Mon, 27 May 2002 05:15:03 -0700 Subject: [PATCH] [PATCH] avoid sys_sync livelocks This makes sure that sys_sync() will terminate. It counts up the number of dirty pages in the machine and will refuse to write out more than 1.25 times this number of pages. This function is called twice on the sys_sync() path, so the kernel will actually write 2.5x the number of initially-dirty pages before giving up. --- fs/fs-writeback.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index b1b79399539f..dae51694ae43 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -325,11 +325,21 @@ static void __wait_on_locked(struct list_head *head) * writeback and wait upon the filesystem's dirty inodes. The caller will * do this in two passes - one to write, and one to wait. WB_SYNC_HOLD is * used to park the written inodes on sb->s_dirty for the wait pass. + * + * A finite limit is set on the number of pages which will be written. + * To prevent infinite livelock of sys_sync(). */ void sync_inodes_sb(struct super_block *sb, int wait) { + struct page_state ps; + int nr_to_write; + + get_page_state(&ps); + nr_to_write = ps.nr_dirty + ps.nr_dirty / 4; + spin_lock(&inode_lock); - sync_sb_inodes(sb, wait ? WB_SYNC_ALL : WB_SYNC_HOLD, NULL, NULL); + sync_sb_inodes(sb, wait ? WB_SYNC_ALL : WB_SYNC_HOLD, + &nr_to_write, NULL); if (wait) __wait_on_locked(&sb->s_locked_inodes); spin_unlock(&inode_lock); -- 2.30.9