From: Wu Fengguang Date: Thu, 14 Apr 2011 13:52:37 +0000 (-0600) Subject: writeback: fix dirtied pages accounting on sub-page writes X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=d3bc1fef9389e409a772ea174a5e41a6f93d9b7b;p=openwrt%2Fstaging%2Fblogic.git writeback: fix dirtied pages accounting on sub-page writes When dd in 512bytes, generic_perform_write() calls balance_dirty_pages_ratelimited() 8 times for the same page, but obviously the page is only dirtied once. Fix it by accounting tsk->nr_dirtied and bdp_ratelimits at page dirty time. Acked-by: Jan Kara Acked-by: Peter Zijlstra Signed-off-by: Wu Fengguang --- diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 619c445fc03c..5d1ef5d8613a 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1258,8 +1258,6 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, if (bdi->dirty_exceeded) ratelimit = min(ratelimit, 32 >> (PAGE_SHIFT - 10)); - current->nr_dirtied += nr_pages_dirtied; - preempt_disable(); /* * This prevents one CPU to accumulate too many dirtied pages without @@ -1270,12 +1268,9 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, p = &__get_cpu_var(bdp_ratelimits); if (unlikely(current->nr_dirtied >= ratelimit)) *p = 0; - else { - *p += nr_pages_dirtied; - if (unlikely(*p >= ratelimit_pages)) { - *p = 0; - ratelimit = 0; - } + else if (unlikely(*p >= ratelimit_pages)) { + *p = 0; + ratelimit = 0; } /* * Pick up the dirtied pages by the exited tasks. This avoids lots of @@ -1768,6 +1763,8 @@ void account_page_dirtied(struct page *page, struct address_space *mapping) __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE); __inc_bdi_stat(mapping->backing_dev_info, BDI_DIRTIED); task_io_account_write(PAGE_CACHE_SIZE); + current->nr_dirtied++; + this_cpu_inc(bdp_ratelimits); } } EXPORT_SYMBOL(account_page_dirtied);