|
@@ -700,6 +700,7 @@ struct pagemapread {
|
|
|
|
|
|
#define PM_PRESENT PM_STATUS(4LL)
|
|
#define PM_PRESENT PM_STATUS(4LL)
|
|
#define PM_SWAP PM_STATUS(2LL)
|
|
#define PM_SWAP PM_STATUS(2LL)
|
|
|
|
+#define PM_FILE PM_STATUS(1LL)
|
|
#define PM_NOT_PRESENT PM_PSHIFT(PAGE_SHIFT)
|
|
#define PM_NOT_PRESENT PM_PSHIFT(PAGE_SHIFT)
|
|
#define PM_END_OF_BUFFER 1
|
|
#define PM_END_OF_BUFFER 1
|
|
|
|
|
|
@@ -733,22 +734,33 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end,
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-static u64 swap_pte_to_pagemap_entry(pte_t pte)
|
|
|
|
|
|
+static void pte_to_pagemap_entry(pagemap_entry_t *pme,
|
|
|
|
+ struct vm_area_struct *vma, unsigned long addr, pte_t pte)
|
|
{
|
|
{
|
|
- swp_entry_t e = pte_to_swp_entry(pte);
|
|
|
|
- return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void pte_to_pagemap_entry(pagemap_entry_t *pme, pte_t pte)
|
|
|
|
-{
|
|
|
|
- if (is_swap_pte(pte))
|
|
|
|
- *pme = make_pme(PM_PFRAME(swap_pte_to_pagemap_entry(pte))
|
|
|
|
- | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP);
|
|
|
|
- else if (pte_present(pte))
|
|
|
|
- *pme = make_pme(PM_PFRAME(pte_pfn(pte))
|
|
|
|
- | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT);
|
|
|
|
- else
|
|
|
|
|
|
+ u64 frame, flags;
|
|
|
|
+ struct page *page = NULL;
|
|
|
|
+
|
|
|
|
+ if (pte_present(pte)) {
|
|
|
|
+ frame = pte_pfn(pte);
|
|
|
|
+ flags = PM_PRESENT;
|
|
|
|
+ page = vm_normal_page(vma, addr, pte);
|
|
|
|
+ } else if (is_swap_pte(pte)) {
|
|
|
|
+ swp_entry_t entry = pte_to_swp_entry(pte);
|
|
|
|
+
|
|
|
|
+ frame = swp_type(entry) |
|
|
|
|
+ (swp_offset(entry) << MAX_SWAPFILES_SHIFT);
|
|
|
|
+ flags = PM_SWAP;
|
|
|
|
+ if (is_migration_entry(entry))
|
|
|
|
+ page = migration_entry_to_page(entry);
|
|
|
|
+ } else {
|
|
*pme = make_pme(PM_NOT_PRESENT);
|
|
*pme = make_pme(PM_NOT_PRESENT);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (page && !PageAnon(page))
|
|
|
|
+ flags |= PM_FILE;
|
|
|
|
+
|
|
|
|
+ *pme = make_pme(PM_PFRAME(frame) | PM_PSHIFT(PAGE_SHIFT) | flags);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
@@ -815,7 +827,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
|
|
if (vma && (vma->vm_start <= addr) &&
|
|
if (vma && (vma->vm_start <= addr) &&
|
|
!is_vm_hugetlb_page(vma)) {
|
|
!is_vm_hugetlb_page(vma)) {
|
|
pte = pte_offset_map(pmd, addr);
|
|
pte = pte_offset_map(pmd, addr);
|
|
- pte_to_pagemap_entry(&pme, *pte);
|
|
|
|
|
|
+ pte_to_pagemap_entry(&pme, vma, addr, *pte);
|
|
/* unmap before userspace copy */
|
|
/* unmap before userspace copy */
|
|
pte_unmap(pte);
|
|
pte_unmap(pte);
|
|
}
|
|
}
|
|
@@ -869,11 +881,11 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
|
|
* For each page in the address space, this file contains one 64-bit entry
|
|
* For each page in the address space, this file contains one 64-bit entry
|
|
* consisting of the following:
|
|
* consisting of the following:
|
|
*
|
|
*
|
|
- * Bits 0-55 page frame number (PFN) if present
|
|
|
|
|
|
+ * Bits 0-54 page frame number (PFN) if present
|
|
* Bits 0-4 swap type if swapped
|
|
* Bits 0-4 swap type if swapped
|
|
- * Bits 5-55 swap offset if swapped
|
|
|
|
|
|
+ * Bits 5-54 swap offset if swapped
|
|
* Bits 55-60 page shift (page size = 1<<page shift)
|
|
* Bits 55-60 page shift (page size = 1<<page shift)
|
|
- * Bit 61 reserved for future use
|
|
|
|
|
|
+ * Bit 61 page is file-page or shared-anon
|
|
* Bit 62 page swapped
|
|
* Bit 62 page swapped
|
|
* Bit 63 page present
|
|
* Bit 63 page present
|
|
*
|
|
*
|