|
|
@@ -925,15 +925,30 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end,
|
|
|
struct mm_walk *walk)
|
|
|
{
|
|
|
struct pagemapread *pm = walk->private;
|
|
|
- unsigned long addr;
|
|
|
+ unsigned long addr = start;
|
|
|
int err = 0;
|
|
|
- pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
|
|
|
|
|
|
- for (addr = start; addr < end; addr += PAGE_SIZE) {
|
|
|
- err = add_to_pagemap(addr, &pme, pm);
|
|
|
- if (err)
|
|
|
- break;
|
|
|
+ while (addr < end) {
|
|
|
+ struct vm_area_struct *vma = find_vma(walk->mm, addr);
|
|
|
+ pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
|
|
|
+ unsigned long vm_end;
|
|
|
+
|
|
|
+ if (!vma) {
|
|
|
+ vm_end = end;
|
|
|
+ } else {
|
|
|
+ vm_end = min(end, vma->vm_end);
|
|
|
+ if (vma->vm_flags & VM_SOFTDIRTY)
|
|
|
+ pme.pme |= PM_STATUS2(pm->v2, __PM_SOFT_DIRTY);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (; addr < vm_end; addr += PAGE_SIZE) {
|
|
|
+ err = add_to_pagemap(addr, &pme, pm);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+out:
|
|
|
return err;
|
|
|
}
|
|
|
|