+ if (pgd_none(*pgd))
+ return 0;
+ if (pgd_bad(*pgd)) {
+ pgd_ERROR(*pgd);
+ pgd_clear(pgd);
+ return 0;
+ }
+ pud = pud_offset(pgd, address);
+ do {
+ next = (address + PUD_SIZE) & PUD_MASK;
+ if (next > end || !next)
+ next = end;
+ foundaddr = unuse_pud(vma, pud, address, next, entry, page);
+ if (foundaddr)
+ return foundaddr;
+ address = next;
+ pud++;
+ } while (address < end);
+ return 0;
+}
+
+/* vma->vm_mm->page_table_lock is held */
+static unsigned long unuse_vma(struct vm_area_struct *vma,
+ swp_entry_t entry, struct page *page)
+{
+ pgd_t *pgd;
+ unsigned long address, next, end;
+ unsigned long foundaddr;
+
+ if (page->mapping) {
+ address = page_address_in_vma(page, vma);
+ if (address == -EFAULT)
+ return 0;
+ else
+ end = address + PAGE_SIZE;
+ } else {
+ address = vma->vm_start;
+ end = vma->vm_end;
+ }
+ pgd = pgd_offset(vma->vm_mm, address);