summaryrefslogtreecommitdiffstats
path: root/mm/huge_memory.c
diff options
context:
space:
mode:
authorAaron Lu2016-11-29 06:27:31 +0100
committerLinus Torvalds2016-11-29 17:20:24 +0100
commita2ce2666aa3509ac31fac0f540a3502372b7b630 (patch)
tree10b193706622c09b1b23c540359de7d75557a5a7 /mm/huge_memory.c
parentMerge branch 'for-4.9-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git... (diff)
downloadkernel-qcow2-linux-a2ce2666aa3509ac31fac0f540a3502372b7b630.tar.gz
kernel-qcow2-linux-a2ce2666aa3509ac31fac0f540a3502372b7b630.tar.xz
kernel-qcow2-linux-a2ce2666aa3509ac31fac0f540a3502372b7b630.zip
mremap: move_ptes: check pte dirty after its removal
Linus found there still is a race in mremap after commit 5d1904204c99 ("mremap: fix race between mremap() and page cleanning"). As described by Linus: "the issue is that another thread might make the pte be dirty (in the hardware walker, so no locking of ours will make any difference) *after* we checked whether it was dirty, but *before* we removed it from the page tables" Fix it by moving the check after we removed it from the page table. Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Aaron Lu <aaron.lu@intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r--mm/huge_memory.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index eff3de359d50..d4a6e4001512 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1456,9 +1456,9 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
new_ptl = pmd_lockptr(mm, new_pmd);
if (new_ptl != old_ptl)
spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING);
- if (pmd_present(*old_pmd) && pmd_dirty(*old_pmd))
- force_flush = true;
pmd = pmdp_huge_get_and_clear(mm, old_addr, old_pmd);
+ if (pmd_present(pmd) && pmd_dirty(pmd))
+ force_flush = true;
VM_BUG_ON(!pmd_none(*new_pmd));
if (pmd_move_must_withdraw(new_ptl, old_ptl) &&