From 96c5b6e54d7429e69dfb3d8eb2cb4c4ebc945fea Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 10 Feb 2010 22:04:25 +0100 Subject: [PATCH] fs: Fix livelock when syncing a filesystem with write activity We cannot tell writeback_inodes_wb() to write just MAX_WRITEBACK_PAGES when it should really sync more, especially in WB_SYNC_ALL mode. That can easily lead to a livelock when new dirty data is created while we loop inside wb_writeback(). Fix the code to use MAX_WRITEBACK_PAGES only for cases where it is really used for background writeback or kupdate style writeback. In all other cases we don't really need to be afraid about fairness between inodes (which is the only reason for MAX_WRITEBACK_PAGES to exist) and so we can write as many pages as the caller asked. Reported-by: Jan Engelhardt Signed-off-by: Jan Kara --- fs/fs-writeback.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1a7c42c..ad38286 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -763,11 +763,19 @@ static long wb_writeback(struct bdi_writeback *wb, break; wbc.more_io = 0; - wbc.nr_to_write = MAX_WRITEBACK_PAGES; + if (wbc.for_kupdate || wbc.for_background) + wbc.nr_to_write = MAX_WRITEBACK_PAGES; + else + wbc.nr_to_write = args->nr_pages; wbc.pages_skipped = 0; writeback_inodes_wb(wb, &wbc); - args->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write; - wrote += MAX_WRITEBACK_PAGES - wbc.nr_to_write; + if (wbc.for_kupdate || wbc.for_background) { + args->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write; + wrote += MAX_WRITEBACK_PAGES - wbc.nr_to_write; + } else { + wrote += args->nr_pages - wbc.nr_to_write; + args->nr_pages = wbc.nr_to_write; + } /* * If we consumed everything, see if we have more -- 1.6.4.2