From: Zi Yan <ziy@xxxxxxxxxx> Signed-off-by: Zi Yan <ziy@xxxxxxxxxx> --- fs/proc/task_mmu.c | 63 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7fc9b3cc48d3..2ff80a9c8b57 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -430,10 +430,9 @@ static void smaps_page_accumulate(struct mem_size_stats *mss, } static void smaps_account(struct mem_size_stats *mss, struct page *page, - bool compound, bool young, bool dirty, bool locked) + unsigned long size, bool young, bool dirty, bool locked) { - int i, nr = compound ? compound_nr(page) : 1; - unsigned long size = nr * PAGE_SIZE; + int i, nr = size / PAGE_SIZE; /* * First accumulate quantities that depend only on |size| and the type @@ -536,7 +535,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, if (!page) return; - smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), locked); + smaps_account(mss, page, PAGE_SIZE, pte_young(*pte), pte_dirty(*pte), locked); } #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -567,8 +566,44 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, /* pass */; else mss->file_thp += HPAGE_PMD_SIZE; - smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), locked); + smaps_account(mss, page, HPAGE_PMD_SIZE, pmd_young(*pmd), + pmd_dirty(*pmd), locked); } + +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD +static void smaps_pud_entry(pud_t *pud, unsigned long addr, + struct mm_walk *walk) +{ + struct mem_size_stats *mss = walk->private; + struct vm_area_struct *vma = walk->vma; + bool locked = !!(vma->vm_flags & VM_LOCKED); + struct page *page = NULL; + + if (pud_present(*pud)) { + /* FOLL_DUMP will return -EFAULT on huge zero page */ + page = follow_trans_huge_pud(vma, addr, pud, FOLL_DUMP); + } + if (IS_ERR_OR_NULL(page)) + return; + if (PageAnon(page)) + mss->anonymous_thp += HPAGE_PUD_SIZE; + else if (PageSwapBacked(page)) + mss->shmem_thp += HPAGE_PUD_SIZE; + else if (is_zone_device_page(page)) + /* pass */; + else + mss->file_thp += HPAGE_PUD_SIZE; + smaps_account(mss, page, HPAGE_PUD_SIZE, pud_young(*pud), + pud_dirty(*pud), locked); +} +#else +static void smaps_pud_entry(pud_t *pud, unsigned long addr, + struct mm_walk *walk) +{ +} +#endif + + #else static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, struct mm_walk *walk) @@ -576,6 +611,23 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, } #endif +static int smaps_pud_range(pud_t *pud, unsigned long addr, unsigned long end, + struct mm_walk *walk) +{ + struct vm_area_struct *vma = walk->vma; + spinlock_t *ptl; + + ptl = pud_trans_huge_lock(pud, vma); + if (ptl) { + smaps_pud_entry(pud, addr, walk); + spin_unlock(ptl); + walk->action = ACTION_CONTINUE; + } + + cond_resched(); + return 0; +} + static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, struct mm_walk *walk) { @@ -713,6 +765,7 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask, #endif /* HUGETLB_PAGE */ static const struct mm_walk_ops smaps_walk_ops = { + .pud_entry = smaps_pud_range, .pmd_entry = smaps_pte_range, .hugetlb_entry = smaps_hugetlb_range, }; -- 2.28.0