diff options
author | Dave Chinner <dchinner@redhat.com> | 2010-08-23 21:44:34 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2010-08-23 21:44:34 -0400 |
commit | 546a1924224078c6f582e68f890b05b387b42653 (patch) | |
tree | f863df4fd74f85c8177d9eb1467a351cd6d0acfc | |
parent | 4536f2ad8b330453d7ebec0746c4374eadd649b1 (diff) |
writeback: write_cache_pages doesn't terminate at nr_to_write <= 0
I noticed XFS writeback in 2.6.36-rc1 was much slower than it should have
been. Enabling writeback tracing showed:
flush-253:16-8516 [007] 1342952.351608: wbc_writepage: bdi 253:16: towrt=1024 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0
flush-253:16-8516 [007] 1342952.351654: wbc_writepage: bdi 253:16: towrt=1023 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0
flush-253:16-8516 [000] 1342952.369520: wbc_writepage: bdi 253:16: towrt=0 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0
flush-253:16-8516 [000] 1342952.369542: wbc_writepage: bdi 253:16: towrt=-1 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0
flush-253:16-8516 [000] 1342952.369549: wbc_writepage: bdi 253:16: towrt=-2 skip=0 mode=0 kupd=0 bgrd=1 reclm=0 cyclic=1 more=0 older=0x0 start=0x0 end=0x0
Writeback is not terminating in background writeback if ->writepage is
returning with wbc->nr_to_write == 0, resulting in sub-optimal single page
writeback on XFS.
Fix the write_cache_pages loop to terminate correctly when this situation
occurs and so prevent this sub-optimal background writeback pattern. This
improves sustained sequential buffered write performance from around
250MB/s to 750MB/s for a 100GB file on an XFS filesystem on my 8p test VM.
Cc:<stable@kernel.org>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Wu Fengguang <fengguang.wu@intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
-rw-r--r-- | mm/page-writeback.c | 26 |
1 files changed, 10 insertions, 16 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index c09ef5219cbe..a803f5e33471 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -985,22 +985,16 @@ continue_unlock: | |||
985 | } | 985 | } |
986 | } | 986 | } |
987 | 987 | ||
988 | if (wbc->nr_to_write > 0) { | 988 | /* |
989 | if (--wbc->nr_to_write == 0 && | 989 | * We stop writing back only if we are not doing |
990 | wbc->sync_mode == WB_SYNC_NONE) { | 990 | * integrity sync. In case of integrity sync we have to |
991 | /* | 991 | * keep going until we have written all the pages |
992 | * We stop writing back only if we are | 992 | * we tagged for writeback prior to entering this loop. |
993 | * not doing integrity sync. In case of | 993 | */ |
994 | * integrity sync we have to keep going | 994 | if (--wbc->nr_to_write <= 0 && |
995 | * because someone may be concurrently | 995 | wbc->sync_mode == WB_SYNC_NONE) { |
996 | * dirtying pages, and we might have | 996 | done = 1; |
997 | * synced a lot of newly appeared dirty | 997 | break; |
998 | * pages, but have not synced all of the | ||
999 | * old dirty pages. | ||
1000 | */ | ||
1001 | done = 1; | ||
1002 | break; | ||
1003 | } | ||
1004 | } | 998 | } |
1005 | } | 999 | } |
1006 | pagevec_release(&pvec); | 1000 | pagevec_release(&pvec); |