diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-02-29 09:55:22 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-02-29 09:55:22 +0100 |
commit | 39a1142dbba04d2e08259bd10a369465c932126b (patch) | |
tree | a2f3b0046a5fe67c07a8f2301413f23c9f57b9b2 /mm/memory.c | |
parent | 65d8fc777f6dcfee12785c057a6b57f679641c90 (diff) | |
parent | fc77dbd34c5c99bce46d40a2491937c3bcbd10af (diff) |
Merge tag 'v4.5-rc6' into locking/core, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/mm/memory.c b/mm/memory.c index 635451abc8f7..8132787ae4d5 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3404,8 +3404,18 @@ static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(pmd_none(*pmd)) && unlikely(__pte_alloc(mm, vma, pmd, address))) return VM_FAULT_OOM; - /* if an huge pmd materialized from under us just retry later */ - if (unlikely(pmd_trans_huge(*pmd) || pmd_devmap(*pmd))) + /* + * If a huge pmd materialized under us just retry later. Use + * pmd_trans_unstable() instead of pmd_trans_huge() to ensure the pmd + * didn't become pmd_trans_huge under us and then back to pmd_none, as + * a result of MADV_DONTNEED running immediately after a huge pmd fault + * in a different thread of this mm, in turn leading to a misleading + * pmd_trans_huge() retval. All we have to ensure is that it is a + * regular pmd that we can walk with pte_offset_map() and we can do that + * through an atomic read in C, which is what pmd_trans_unstable() + * provides. + */ + if (unlikely(pmd_trans_unstable(pmd) || pmd_devmap(*pmd))) return 0; /* * A regular pmd is established and it can't morph into a huge pmd |