summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorNick Piggin2008-08-20 23:09:18 +0200
committerLinus Torvalds2008-08-21 00:40:32 +0200
commit479db0bf408e65baa14d2a9821abfcbc0804b847 (patch)
treeacdaaed567afefa36ac2fe27cfe22cfefeb50cd5 /include
parentfix setpriority(PRIO_PGRP) thread iterator breakage (diff)
downloadkernel-qcow2-linux-479db0bf408e65baa14d2a9821abfcbc0804b847.tar.gz
kernel-qcow2-linux-479db0bf408e65baa14d2a9821abfcbc0804b847.tar.xz
kernel-qcow2-linux-479db0bf408e65baa14d2a9821abfcbc0804b847.zip
mm: dirty page tracking race fix
There is a race with dirty page accounting where a page may not properly be accounted for. clear_page_dirty_for_io() calls page_mkclean; then TestClearPageDirty. page_mkclean walks the rmaps for that page, and for each one it cleans and write protects the pte if it was dirty. It uses page_check_address to find the pte. That function has a shortcut to avoid the ptl if the pte is not present. Unfortunately, the pte can be switched to not-present then back to present by other code while holding the page table lock -- this should not be a signal for page_mkclean to ignore that pte, because it may be dirty. For example, powerpc64's set_pte_at will clear a previously present pte before setting it to the desired value. There may also be other code in core mm or in arch which do similar things. The consequence of the bug is loss of data integrity due to msync, and loss of dirty page accounting accuracy. XIP's __xip_unmap could easily also be unreliable (depending on the exact XIP locking scheme), which can lead to data corruption. Fix this by having an option to always take ptl to check the pte in page_check_address. It's possible to retain this optimization for page_referenced and try_to_unmap. Signed-off-by: Nick Piggin <npiggin@suse.de> Cc: Jared Hulbert <jaredeh@gmail.com> Cc: Carsten Otte <cotte@freenet.de> Cc: Hugh Dickins <hugh@veritas.com> 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>
Diffstat (limited to 'include')
-rw-r--r--include/linux/rmap.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 69407f85e10b..fed6f5e0b411 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -102,7 +102,7 @@ int try_to_unmap(struct page *, int ignore_refs);
* Called from mm/filemap_xip.c to unmap empty zero page
*/
pte_t *page_check_address(struct page *, struct mm_struct *,
- unsigned long, spinlock_t **);
+ unsigned long, spinlock_t **, int);
/*
* Used by swapoff to help locate where page is expected in vma.