aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mm.h
diff options
context:
space:
mode:
authorPeter Feiner <pfeiner@google.com>2014-10-13 18:55:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 20:18:28 -0400
commit64e455079e1bd7787cc47be30b7f601ce682a5f6 (patch)
tree05193bd91be3ffc0d33ddd3ffb654ef4c23778f9 /include/linux/mm.h
parent63a12d9d01831208a47f5c0fbbf93f503d1fb162 (diff)
mm: softdirty: enable write notifications on VMAs after VM_SOFTDIRTY cleared
For VMAs that don't want write notifications, PTEs created for read faults have their write bit set. If the read fault happens after VM_SOFTDIRTY is cleared, then the PTE's softdirty bit will remain clear after subsequent writes. Here's a simple code snippet to demonstrate the bug: char* m = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); system("echo 4 > /proc/$PPID/clear_refs"); /* clear VM_SOFTDIRTY */ assert(*m == '\0'); /* new PTE allows write access */ assert(!soft_dirty(x)); *m = 'x'; /* should dirty the page */ assert(soft_dirty(x)); /* fails */ With this patch, write notifications are enabled when VM_SOFTDIRTY is cleared. Furthermore, to avoid unnecessary faults, write notifications are disabled when VM_SOFTDIRTY is set. As a side effect of enabling and disabling write notifications with care, this patch fixes a bug in mprotect where vm_page_prot bits set by drivers were zapped on mprotect. An analogous bug was fixed in mmap by commit c9d0bf241451 ("mm: uncached vma support with writenotify"). Signed-off-by: Peter Feiner <pfeiner@google.com> Reported-by: Peter Feiner <pfeiner@google.com> Suggested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Jamie Liu <jamieliu@google.com> Cc: Hugh Dickins <hughd@google.com> Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r--include/linux/mm.h5
1 files changed, 5 insertions, 0 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 4cd45cb95e6d..02d11ee7f19d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1974,11 +1974,16 @@ static inline struct vm_area_struct *find_exact_vma(struct mm_struct *mm,
1974 1974
1975#ifdef CONFIG_MMU 1975#ifdef CONFIG_MMU
1976pgprot_t vm_get_page_prot(unsigned long vm_flags); 1976pgprot_t vm_get_page_prot(unsigned long vm_flags);
1977void vma_set_page_prot(struct vm_area_struct *vma);
1977#else 1978#else
1978static inline pgprot_t vm_get_page_prot(unsigned long vm_flags) 1979static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
1979{ 1980{
1980 return __pgprot(0); 1981 return __pgprot(0);
1981} 1982}
1983static inline void vma_set_page_prot(struct vm_area_struct *vma)
1984{
1985 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
1986}
1982#endif 1987#endif
1983 1988
1984#ifdef CONFIG_NUMA_BALANCING 1989#ifdef CONFIG_NUMA_BALANCING