aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page-writeback.c
diff options
context:
space:
mode:
authorWu Fengguang <fengguang.wu@intel.com>2009-09-23 09:56:00 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-09-25 12:08:24 -0400
commit3a2e9a5a2afc1a2d2c548b8987f133235cebe933 (patch)
treecb05d2873b2701ded758a7087de5af2932a97736 /mm/page-writeback.c
parenta5989bdc981ec85e0734ac22519cc0b780813d7b (diff)
writeback: balance_dirty_pages() shall write more than dirtied pages
Some filesystem may choose to write much more than ratelimit_pages before calling balance_dirty_pages_ratelimited_nr(). So it is safer to determine number to write based on real number of dirtied pages. Otherwise it is possible that loop { btrfs_file_write(): dirty 1024 pages balance_dirty_pages(): write up to 48 pages (= ratelimit_pages * 1.5) } in which the writeback rate cannot keep up with dirty rate, and the dirty pages go all the way beyond dirty_thresh. The increased write_chunk may make the dirtier more bumpy. So filesystems shall be take care not to dirty too much at a time (eg. > 4MB) without checking the ratelimit. Signed-off-by: Wu Fengguang <fengguang.wu@intel.com> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'mm/page-writeback.c')
-rw-r--r--mm/page-writeback.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 5f378dd58802..cbd4cba468bd 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -44,12 +44,15 @@ static long ratelimit_pages = 32;
44/* 44/*
45 * When balance_dirty_pages decides that the caller needs to perform some 45 * When balance_dirty_pages decides that the caller needs to perform some
46 * non-background writeback, this is how many pages it will attempt to write. 46 * non-background writeback, this is how many pages it will attempt to write.
47 * It should be somewhat larger than RATELIMIT_PAGES to ensure that reasonably 47 * It should be somewhat larger than dirtied pages to ensure that reasonably
48 * large amounts of I/O are submitted. 48 * large amounts of I/O are submitted.
49 */ 49 */
50static inline long sync_writeback_pages(void) 50static inline long sync_writeback_pages(unsigned long dirtied)
51{ 51{
52 return ratelimit_pages + ratelimit_pages / 2; 52 if (dirtied < ratelimit_pages)
53 dirtied = ratelimit_pages;
54
55 return dirtied + dirtied / 2;
53} 56}
54 57
55/* The following parameters are exported via /proc/sys/vm */ 58/* The following parameters are exported via /proc/sys/vm */
@@ -477,7 +480,8 @@ get_dirty_limits(unsigned long *pbackground, unsigned long *pdirty,
477 * If we're over `background_thresh' then pdflush is woken to perform some 480 * If we're over `background_thresh' then pdflush is woken to perform some
478 * writeout. 481 * writeout.
479 */ 482 */
480static void balance_dirty_pages(struct address_space *mapping) 483static void balance_dirty_pages(struct address_space *mapping,
484 unsigned long write_chunk)
481{ 485{
482 long nr_reclaimable, bdi_nr_reclaimable; 486 long nr_reclaimable, bdi_nr_reclaimable;
483 long nr_writeback, bdi_nr_writeback; 487 long nr_writeback, bdi_nr_writeback;
@@ -485,7 +489,6 @@ static void balance_dirty_pages(struct address_space *mapping)
485 unsigned long dirty_thresh; 489 unsigned long dirty_thresh;
486 unsigned long bdi_thresh; 490 unsigned long bdi_thresh;
487 unsigned long pages_written = 0; 491 unsigned long pages_written = 0;
488 unsigned long write_chunk = sync_writeback_pages();
489 unsigned long pause = 1; 492 unsigned long pause = 1;
490 493
491 struct backing_dev_info *bdi = mapping->backing_dev_info; 494 struct backing_dev_info *bdi = mapping->backing_dev_info;
@@ -640,9 +643,10 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
640 p = &__get_cpu_var(bdp_ratelimits); 643 p = &__get_cpu_var(bdp_ratelimits);
641 *p += nr_pages_dirtied; 644 *p += nr_pages_dirtied;
642 if (unlikely(*p >= ratelimit)) { 645 if (unlikely(*p >= ratelimit)) {
646 ratelimit = sync_writeback_pages(*p);
643 *p = 0; 647 *p = 0;
644 preempt_enable(); 648 preempt_enable();
645 balance_dirty_pages(mapping); 649 balance_dirty_pages(mapping, ratelimit);
646 return; 650 return;
647 } 651 }
648 preempt_enable(); 652 preempt_enable();