Commit 8d04539d authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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.
parent ce677ce2
...@@ -325,11 +325,21 @@ static void __wait_on_locked(struct list_head *head) ...@@ -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 * 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 * 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. * 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) 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); 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) if (wait)
__wait_on_locked(&sb->s_locked_inodes); __wait_on_locked(&sb->s_locked_inodes);
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment