diff options
Diffstat (limited to 'fs/proc/task_mmu.c')
| -rw-r--r-- | fs/proc/task_mmu.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7faaf2acc570..4540b8f76f16 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -125,7 +125,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
| 125 | if (!priv->task) | 125 | if (!priv->task) |
| 126 | return ERR_PTR(-ESRCH); | 126 | return ERR_PTR(-ESRCH); |
| 127 | 127 | ||
| 128 | mm = mm_for_maps(priv->task); | 128 | mm = mm_access(priv->task, PTRACE_MODE_READ); |
| 129 | if (!mm || IS_ERR(mm)) | 129 | if (!mm || IS_ERR(mm)) |
| 130 | return mm; | 130 | return mm; |
| 131 | down_read(&mm->mmap_sem); | 131 | down_read(&mm->mmap_sem); |
| @@ -393,6 +393,7 @@ struct mem_size_stats { | |||
| 393 | unsigned long anonymous; | 393 | unsigned long anonymous; |
| 394 | unsigned long anonymous_thp; | 394 | unsigned long anonymous_thp; |
| 395 | unsigned long swap; | 395 | unsigned long swap; |
| 396 | unsigned long nonlinear; | ||
| 396 | u64 pss; | 397 | u64 pss; |
| 397 | }; | 398 | }; |
| 398 | 399 | ||
| @@ -402,24 +403,33 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr, | |||
| 402 | { | 403 | { |
| 403 | struct mem_size_stats *mss = walk->private; | 404 | struct mem_size_stats *mss = walk->private; |
| 404 | struct vm_area_struct *vma = mss->vma; | 405 | struct vm_area_struct *vma = mss->vma; |
| 405 | struct page *page; | 406 | pgoff_t pgoff = linear_page_index(vma, addr); |
| 407 | struct page *page = NULL; | ||
| 406 | int mapcount; | 408 | int mapcount; |
| 407 | 409 | ||
| 408 | if (is_swap_pte(ptent)) { | 410 | if (pte_present(ptent)) { |
| 409 | mss->swap += ptent_size; | 411 | page = vm_normal_page(vma, addr, ptent); |
| 410 | return; | 412 | } else if (is_swap_pte(ptent)) { |
| 413 | swp_entry_t swpent = pte_to_swp_entry(ptent); | ||
| 414 | |||
| 415 | if (!non_swap_entry(swpent)) | ||
| 416 | mss->swap += ptent_size; | ||
| 417 | else if (is_migration_entry(swpent)) | ||
| 418 | page = migration_entry_to_page(swpent); | ||
| 419 | } else if (pte_file(ptent)) { | ||
| 420 | if (pte_to_pgoff(ptent) != pgoff) | ||
| 421 | mss->nonlinear += ptent_size; | ||
| 411 | } | 422 | } |
| 412 | 423 | ||
| 413 | if (!pte_present(ptent)) | ||
| 414 | return; | ||
| 415 | |||
| 416 | page = vm_normal_page(vma, addr, ptent); | ||
| 417 | if (!page) | 424 | if (!page) |
| 418 | return; | 425 | return; |
| 419 | 426 | ||
| 420 | if (PageAnon(page)) | 427 | if (PageAnon(page)) |
| 421 | mss->anonymous += ptent_size; | 428 | mss->anonymous += ptent_size; |
| 422 | 429 | ||
| 430 | if (page->index != pgoff) | ||
| 431 | mss->nonlinear += ptent_size; | ||
| 432 | |||
| 423 | mss->resident += ptent_size; | 433 | mss->resident += ptent_size; |
| 424 | /* Accumulate the size in pages that have been accessed. */ | 434 | /* Accumulate the size in pages that have been accessed. */ |
| 425 | if (pte_young(ptent) || PageReferenced(page)) | 435 | if (pte_young(ptent) || PageReferenced(page)) |
| @@ -521,6 +531,10 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) | |||
| 521 | (vma->vm_flags & VM_LOCKED) ? | 531 | (vma->vm_flags & VM_LOCKED) ? |
| 522 | (unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0); | 532 | (unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0); |
| 523 | 533 | ||
| 534 | if (vma->vm_flags & VM_NONLINEAR) | ||
| 535 | seq_printf(m, "Nonlinear: %8lu kB\n", | ||
| 536 | mss.nonlinear >> 10); | ||
| 537 | |||
| 524 | if (m->count < m->size) /* vma is copied successfully */ | 538 | if (m->count < m->size) /* vma is copied successfully */ |
| 525 | m->version = (vma != get_gate_vma(task->mm)) | 539 | m->version = (vma != get_gate_vma(task->mm)) |
| 526 | ? vma->vm_start : 0; | 540 | ? vma->vm_start : 0; |
| @@ -700,6 +714,7 @@ struct pagemapread { | |||
| 700 | 714 | ||
| 701 | #define PM_PRESENT PM_STATUS(4LL) | 715 | #define PM_PRESENT PM_STATUS(4LL) |
| 702 | #define PM_SWAP PM_STATUS(2LL) | 716 | #define PM_SWAP PM_STATUS(2LL) |
| 717 | #define PM_FILE PM_STATUS(1LL) | ||
| 703 | #define PM_NOT_PRESENT PM_PSHIFT(PAGE_SHIFT) | 718 | #define PM_NOT_PRESENT PM_PSHIFT(PAGE_SHIFT) |
| 704 | #define PM_END_OF_BUFFER 1 | 719 | #define PM_END_OF_BUFFER 1 |
| 705 | 720 | ||
| @@ -733,22 +748,33 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end, | |||
| 733 | return err; | 748 | return err; |
| 734 | } | 749 | } |
| 735 | 750 | ||
| 736 | static u64 swap_pte_to_pagemap_entry(pte_t pte) | 751 | static void pte_to_pagemap_entry(pagemap_entry_t *pme, |
| 752 | struct vm_area_struct *vma, unsigned long addr, pte_t pte) | ||
| 737 | { | 753 | { |
| 738 | swp_entry_t e = pte_to_swp_entry(pte); | 754 | u64 frame, flags; |
| 739 | return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); | 755 | struct page *page = NULL; |
| 740 | } | 756 | |
| 741 | 757 | if (pte_present(pte)) { | |
| 742 | static void pte_to_pagemap_entry(pagemap_entry_t *pme, pte_t pte) | 758 | frame = pte_pfn(pte); |
| 743 | { | 759 | flags = PM_PRESENT; |
| 744 | if (is_swap_pte(pte)) | 760 | page = vm_normal_page(vma, addr, pte); |
| 745 | *pme = make_pme(PM_PFRAME(swap_pte_to_pagemap_entry(pte)) | 761 | } else if (is_swap_pte(pte)) { |
| 746 | | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP); | 762 | swp_entry_t entry = pte_to_swp_entry(pte); |
| 747 | else if (pte_present(pte)) | 763 | |
| 748 | *pme = make_pme(PM_PFRAME(pte_pfn(pte)) | 764 | frame = swp_type(entry) | |
| 749 | | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT); | 765 | (swp_offset(entry) << MAX_SWAPFILES_SHIFT); |
| 750 | else | 766 | flags = PM_SWAP; |
| 767 | if (is_migration_entry(entry)) | ||
| 768 | page = migration_entry_to_page(entry); | ||
| 769 | } else { | ||
| 751 | *pme = make_pme(PM_NOT_PRESENT); | 770 | *pme = make_pme(PM_NOT_PRESENT); |
| 771 | return; | ||
| 772 | } | ||
| 773 | |||
| 774 | if (page && !PageAnon(page)) | ||
| 775 | flags |= PM_FILE; | ||
| 776 | |||
| 777 | *pme = make_pme(PM_PFRAME(frame) | PM_PSHIFT(PAGE_SHIFT) | flags); | ||
| 752 | } | 778 | } |
| 753 | 779 | ||
| 754 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 780 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| @@ -815,7 +841,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
| 815 | if (vma && (vma->vm_start <= addr) && | 841 | if (vma && (vma->vm_start <= addr) && |
| 816 | !is_vm_hugetlb_page(vma)) { | 842 | !is_vm_hugetlb_page(vma)) { |
| 817 | pte = pte_offset_map(pmd, addr); | 843 | pte = pte_offset_map(pmd, addr); |
| 818 | pte_to_pagemap_entry(&pme, *pte); | 844 | pte_to_pagemap_entry(&pme, vma, addr, *pte); |
| 819 | /* unmap before userspace copy */ | 845 | /* unmap before userspace copy */ |
| 820 | pte_unmap(pte); | 846 | pte_unmap(pte); |
| 821 | } | 847 | } |
| @@ -869,11 +895,11 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask, | |||
| 869 | * For each page in the address space, this file contains one 64-bit entry | 895 | * For each page in the address space, this file contains one 64-bit entry |
| 870 | * consisting of the following: | 896 | * consisting of the following: |
| 871 | * | 897 | * |
| 872 | * Bits 0-55 page frame number (PFN) if present | 898 | * Bits 0-54 page frame number (PFN) if present |
| 873 | * Bits 0-4 swap type if swapped | 899 | * Bits 0-4 swap type if swapped |
| 874 | * Bits 5-55 swap offset if swapped | 900 | * Bits 5-54 swap offset if swapped |
| 875 | * Bits 55-60 page shift (page size = 1<<page shift) | 901 | * Bits 55-60 page shift (page size = 1<<page shift) |
| 876 | * Bit 61 reserved for future use | 902 | * Bit 61 page is file-page or shared-anon |
| 877 | * Bit 62 page swapped | 903 | * Bit 62 page swapped |
| 878 | * Bit 63 page present | 904 | * Bit 63 page present |
| 879 | * | 905 | * |
| @@ -919,7 +945,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
| 919 | if (!pm.buffer) | 945 | if (!pm.buffer) |
| 920 | goto out_task; | 946 | goto out_task; |
| 921 | 947 | ||
| 922 | mm = mm_for_maps(task); | 948 | mm = mm_access(task, PTRACE_MODE_READ); |
| 923 | ret = PTR_ERR(mm); | 949 | ret = PTR_ERR(mm); |
| 924 | if (!mm || IS_ERR(mm)) | 950 | if (!mm || IS_ERR(mm)) |
| 925 | goto out_free; | 951 | goto out_free; |
