Currently there is no way to find out current layout of non-linear mapping. Also there is no way to distinguish ordinary file mapping from non-linear mapping. Now in pagemap non-linear pte can be recognized as present swapped file-backed, or as non-present non-swapped file-backed for non-present non-linear file-pte: present swapped file data description 0 0 0 null non-present 0 0 1 page-index non-linear file-pte 0 1 0 swap-entry anon-page in swap, migration or hwpoison 0 1 1 swap-entry file-page in migration or hwpoison 1 0 0 page-pfn present private-anon or special page 1 0 1 page-pfn present file or shared-anon page 1 1 0 none impossible combination 1 1 1 page-index non-linear file-page [ the last unused combination 1-1-0 can be used for special pages, if anyone want this ] Signed-off-by: Konstantin Khlebnikov <khlebnikov@xxxxxxxxxx> Cc: Pavel Emelyanov <xemul@xxxxxxxxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Hugh Dickins <hughd@xxxxxxxxxx> Cc: Rik van Riel <riel@xxxxxxxxxx> --- Documentation/vm/pagemap.txt | 15 +++++++++++++++ fs/proc/task_mmu.c | 13 +++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Documentation/vm/pagemap.txt b/Documentation/vm/pagemap.txt index 7587493..6800dda 100644 --- a/Documentation/vm/pagemap.txt +++ b/Documentation/vm/pagemap.txt @@ -13,6 +13,7 @@ There are three components to pagemap: fs/proc/task_mmu.c, above pagemap_read): * Bits 0-54 page frame number (PFN) if present + * Bits 0-54 page index for non-linear mappings * Bits 0-4 swap type if swapped * Bits 5-54 swap offset if swapped * Bits 55-60 page shift (page size = 1<<page shift) @@ -26,6 +27,20 @@ There are three components to pagemap: precisely which pages are mapped (or in swap) and comparing mapped pages between processes. + For non-linear file mappings page index is reported instead of PFN. + Non-linear pte can be recognized as present swapped file-backed or + non-present non-swapped file-backed. + + present swapped file data description + 0 0 0 null non-present + 0 0 1 page-index non-linear file-pte + 0 1 0 swap-entry anon-page in swap, migration or hwpoison + 0 1 1 swap-entry file-page in migration or hwpoison + 1 0 0 page-pfn present private-anon or special page + 1 0 1 page-pfn present file or shared-anon page + 1 1 0 none impossible combination + 1 1 1 page-index non-linear file-page + Efficient users of this interface will use /proc/pid/maps to determine which areas of memory are actually mapped and llseek to skip over unmapped regions. diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index bc3df31..fcc802f 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -744,6 +744,9 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, frame = pte_pfn(pte); flags = PM_PRESENT; page = vm_normal_page(vma, addr, pte); + } if (pte_file(pte)) { + frame = pte_to_pgoff(pte); + flags = PM_FILE; } if (is_swap_pte(pte)) { swp_entry_t entry = pte_to_swp_entry(pte); @@ -755,8 +758,13 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, } else return; - if (page && !PageAnon(page)) - flags |= PM_FILE; + if (page) { + if (vma->vm_flags & VM_NONLINEAR) { + frame = page->index; + flags = PM_FILE | PM_SWAP | PM_PRESENT; + } else if (!PageAnon(page)) + flags |= PM_FILE; + } *pme = make_pme(PM_PFRAME(frame) | PM_PSHIFT(PAGE_SHIFT) | flags); } @@ -874,6 +882,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask, * consisting of the following: * * Bits 0-54 page frame number (PFN) if present + * Bits 0-54 page index for non-linear mappings * Bits 0-4 swap type if swapped * Bits 5-54 swap offset if swapped * Bits 55-60 page shift (page size = 1<<page shift) -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>