|
@@ -1,6 +1,7 @@
|
|
#include <linux/mm.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/highmem.h>
|
|
#include <linux/highmem.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/sched.h>
|
|
|
|
+#include <linux/hugetlb.h>
|
|
|
|
|
|
static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
|
|
static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
|
|
struct mm_walk *walk)
|
|
struct mm_walk *walk)
|
|
@@ -107,6 +108,7 @@ int walk_page_range(unsigned long addr, unsigned long end,
|
|
pgd_t *pgd;
|
|
pgd_t *pgd;
|
|
unsigned long next;
|
|
unsigned long next;
|
|
int err = 0;
|
|
int err = 0;
|
|
|
|
+ struct vm_area_struct *vma;
|
|
|
|
|
|
if (addr >= end)
|
|
if (addr >= end)
|
|
return err;
|
|
return err;
|
|
@@ -117,11 +119,22 @@ int walk_page_range(unsigned long addr, unsigned long end,
|
|
pgd = pgd_offset(walk->mm, addr);
|
|
pgd = pgd_offset(walk->mm, addr);
|
|
do {
|
|
do {
|
|
next = pgd_addr_end(addr, end);
|
|
next = pgd_addr_end(addr, end);
|
|
|
|
+
|
|
|
|
+ /* skip hugetlb vma to avoid hugepage PMD being cleared
|
|
|
|
+ * in pmd_none_or_clear_bad(). */
|
|
|
|
+ vma = find_vma(walk->mm, addr);
|
|
|
|
+ if (vma && is_vm_hugetlb_page(vma)) {
|
|
|
|
+ if (vma->vm_end < next)
|
|
|
|
+ next = vma->vm_end;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (pgd_none_or_clear_bad(pgd)) {
|
|
if (pgd_none_or_clear_bad(pgd)) {
|
|
if (walk->pte_hole)
|
|
if (walk->pte_hole)
|
|
err = walk->pte_hole(addr, next, walk);
|
|
err = walk->pte_hole(addr, next, walk);
|
|
if (err)
|
|
if (err)
|
|
break;
|
|
break;
|
|
|
|
+ pgd++;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
if (walk->pgd_entry)
|
|
if (walk->pgd_entry)
|
|
@@ -131,7 +144,8 @@ int walk_page_range(unsigned long addr, unsigned long end,
|
|
err = walk_pud_range(pgd, addr, next, walk);
|
|
err = walk_pud_range(pgd, addr, next, walk);
|
|
if (err)
|
|
if (err)
|
|
break;
|
|
break;
|
|
- } while (pgd++, addr = next, addr != end);
|
|
|
|
|
|
+ pgd++;
|
|
|
|
+ } while (addr = next, addr != end);
|
|
|
|
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|