diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-07-14 18:13:41 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-07-14 18:13:41 +0200 |
commit | 03fe805a098422d27cbbbad29a54ff1349da3622 (patch) | |
tree | 0db9cc9a701203ddcee58e5b907d4fb8ad31b421 /mm/rmap.c | |
parent | 50dd9050e45ce11c575eabcaee8a914caf78fb74 (diff) | |
parent | 5646eda5851e6cfdfa22d41895e3f5daffa643d3 (diff) |
Merge branch 'topic/monotonic' into for-next
Diffstat (limited to 'mm/rmap.c')
-rw-r--r-- | mm/rmap.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/mm/rmap.c b/mm/rmap.c index bf05fc872ae8..b7e94ebbd09e 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -569,6 +569,7 @@ pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address) pgd_t *pgd; pud_t *pud; pmd_t *pmd = NULL; + pmd_t pmde; pgd = pgd_offset(mm, address); if (!pgd_present(*pgd)) @@ -579,7 +580,13 @@ pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address) goto out; pmd = pmd_offset(pud, address); - if (!pmd_present(*pmd)) + /* + * Some THP functions use the sequence pmdp_clear_flush(), set_pmd_at() + * without holding anon_vma lock for write. So when looking for a + * genuine pmde (in which to find pte), test present and !THP together. + */ + pmde = ACCESS_ONCE(*pmd); + if (!pmd_present(pmde) || pmd_trans_huge(pmde)) pmd = NULL; out: return pmd; @@ -615,9 +622,6 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm, if (!pmd) return NULL; - if (pmd_trans_huge(*pmd)) - return NULL; - pte = pte_offset_map(pmd, address); /* Make a quick check before getting the lock */ if (!sync && !pte_present(*pte)) { |