aboutsummaryrefslogtreecommitdiffstats
path: root/mm/pagewalk.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/pagewalk.c')
-rw-r--r--mm/pagewalk.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index a286915e23ef..7b47a57b6646 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -120,15 +120,31 @@ int walk_page_range(unsigned long addr, unsigned long end,
120 do { 120 do {
121 next = pgd_addr_end(addr, end); 121 next = pgd_addr_end(addr, end);
122 122
123 /* skip hugetlb vma to avoid hugepage PMD being cleared 123 /*
124 * in pmd_none_or_clear_bad(). */ 124 * handle hugetlb vma individually because pagetable walk for
125 * the hugetlb page is dependent on the architecture and
126 * we can't handled it in the same manner as non-huge pages.
127 */
125 vma = find_vma(walk->mm, addr); 128 vma = find_vma(walk->mm, addr);
129#ifdef CONFIG_HUGETLB_PAGE
126 if (vma && is_vm_hugetlb_page(vma)) { 130 if (vma && is_vm_hugetlb_page(vma)) {
131 pte_t *pte;
132 struct hstate *hs;
133
127 if (vma->vm_end < next) 134 if (vma->vm_end < next)
128 next = vma->vm_end; 135 next = vma->vm_end;
136 hs = hstate_vma(vma);
137 pte = huge_pte_offset(walk->mm,
138 addr & huge_page_mask(hs));
139 if (pte && !huge_pte_none(huge_ptep_get(pte))
140 && walk->hugetlb_entry)
141 err = walk->hugetlb_entry(pte, addr,
142 next, walk);
143 if (err)
144 break;
129 continue; 145 continue;
130 } 146 }
131 147#endif
132 if (pgd_none_or_clear_bad(pgd)) { 148 if (pgd_none_or_clear_bad(pgd)) {
133 if (walk->pte_hole) 149 if (walk->pte_hole)
134 err = walk->pte_hole(addr, next, walk); 150 err = walk->pte_hole(addr, next, walk);