aboutsummaryrefslogtreecommitdiffstats
path: root/mm/rmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/rmap.c')
-rw-r--r--mm/rmap.c12
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)
569 pgd_t *pgd; 569 pgd_t *pgd;
570 pud_t *pud; 570 pud_t *pud;
571 pmd_t *pmd = NULL; 571 pmd_t *pmd = NULL;
572 pmd_t pmde;
572 573
573 pgd = pgd_offset(mm, address); 574 pgd = pgd_offset(mm, address);
574 if (!pgd_present(*pgd)) 575 if (!pgd_present(*pgd))
@@ -579,7 +580,13 @@ pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address)
579 goto out; 580 goto out;
580 581
581 pmd = pmd_offset(pud, address); 582 pmd = pmd_offset(pud, address);
582 if (!pmd_present(*pmd)) 583 /*
584 * Some THP functions use the sequence pmdp_clear_flush(), set_pmd_at()
585 * without holding anon_vma lock for write. So when looking for a
586 * genuine pmde (in which to find pte), test present and !THP together.
587 */
588 pmde = ACCESS_ONCE(*pmd);
589 if (!pmd_present(pmde) || pmd_trans_huge(pmde))
583 pmd = NULL; 590 pmd = NULL;
584out: 591out:
585 return pmd; 592 return pmd;
@@ -615,9 +622,6 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
615 if (!pmd) 622 if (!pmd)
616 return NULL; 623 return NULL;
617 624
618 if (pmd_trans_huge(*pmd))
619 return NULL;
620
621 pte = pte_offset_map(pmd, address); 625 pte = pte_offset_map(pmd, address);
622 /* Make a quick check before getting the lock */ 626 /* Make a quick check before getting the lock */
623 if (!sync && !pte_present(*pte)) { 627 if (!sync && !pte_present(*pte)) {