Commit 1cf6e7d83bf334cc5916137862c920a97aabc018

Authored by Nick Piggin
Committed by Linus Torvalds
1 parent 610d18f412

mm: task dirty accounting fix

YAMAMOTO-san noticed that task_dirty_inc doesn't seem to be called properly for
cases where set_page_dirty is not used to dirty a page (eg. mark_buffer_dirty).

Additionally, there is some inconsistency about when task_dirty_inc is
called.  It is used for dirty balancing, however it even gets called for
__set_page_dirty_no_writeback.

So rather than increment it in a set_page_dirty wrapper, move it down to
exactly where the dirty page accounting stats are incremented.

Cc: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 5 additions and 10 deletions Side-by-side Diff

... ... @@ -777,6 +777,7 @@
777 777 __inc_zone_page_state(page, NR_FILE_DIRTY);
778 778 __inc_bdi_stat(mapping->backing_dev_info,
779 779 BDI_RECLAIMABLE);
  780 + task_dirty_inc(current);
780 781 task_io_account_write(PAGE_CACHE_SIZE);
781 782 }
782 783 radix_tree_tag_set(&mapping->page_tree,
... ... @@ -1159,6 +1159,7 @@
1159 1159  
1160 1160 /* mm/page-writeback.c */
1161 1161 int write_one_page(struct page *page, int wait);
  1162 +void task_dirty_inc(struct task_struct *tsk);
1162 1163  
1163 1164 /* readahead.c */
1164 1165 #define VM_MAX_READAHEAD 128 /* kbytes */
... ... @@ -240,7 +240,7 @@
240 240 }
241 241 EXPORT_SYMBOL_GPL(bdi_writeout_inc);
242 242  
243   -static inline void task_dirty_inc(struct task_struct *tsk)
  243 +void task_dirty_inc(struct task_struct *tsk)
244 244 {
245 245 prop_inc_single(&vm_dirties, &tsk->dirties);
246 246 }
... ... @@ -1230,6 +1230,7 @@
1230 1230 __inc_zone_page_state(page, NR_FILE_DIRTY);
1231 1231 __inc_bdi_stat(mapping->backing_dev_info,
1232 1232 BDI_RECLAIMABLE);
  1233 + task_dirty_inc(current);
1233 1234 task_io_account_write(PAGE_CACHE_SIZE);
1234 1235 }
1235 1236 radix_tree_tag_set(&mapping->page_tree,
... ... @@ -1262,7 +1263,7 @@
1262 1263 * If the mapping doesn't provide a set_page_dirty a_op, then
1263 1264 * just fall through and assume that it wants buffer_heads.
1264 1265 */
1265   -static int __set_page_dirty(struct page *page)
  1266 +int set_page_dirty(struct page *page)
1266 1267 {
1267 1268 struct address_space *mapping = page_mapping(page);
1268 1269  
... ... @@ -1279,14 +1280,6 @@
1279 1280 return 1;
1280 1281 }
1281 1282 return 0;
1282   -}
1283   -
1284   -int set_page_dirty(struct page *page)
1285   -{
1286   - int ret = __set_page_dirty(page);
1287   - if (ret)
1288   - task_dirty_inc(current);
1289   - return ret;
1290 1283 }
1291 1284 EXPORT_SYMBOL(set_page_dirty);
1292 1285