mm: hugetlb: proc: add hugetlb-related fields to /proc/PID/smaps
[linux-2.6-block.git] / fs / proc / task_mmu.c
index e2d46adb54b42a76608a0cbf938d55529bd6c851..5988b83836fb111e6929d1b67ac0a58775b0378b 100644 (file)
@@ -446,6 +446,8 @@ struct mem_size_stats {
        unsigned long anonymous;
        unsigned long anonymous_thp;
        unsigned long swap;
+       unsigned long shared_hugetlb;
+       unsigned long private_hugetlb;
        u64 pss;
        u64 swap_pss;
 };
@@ -625,12 +627,44 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
        seq_putc(m, '\n');
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
+static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,
+                                unsigned long addr, unsigned long end,
+                                struct mm_walk *walk)
+{
+       struct mem_size_stats *mss = walk->private;
+       struct vm_area_struct *vma = walk->vma;
+       struct page *page = NULL;
+
+       if (pte_present(*pte)) {
+               page = vm_normal_page(vma, addr, *pte);
+       } else if (is_swap_pte(*pte)) {
+               swp_entry_t swpent = pte_to_swp_entry(*pte);
+
+               if (is_migration_entry(swpent))
+                       page = migration_entry_to_page(swpent);
+       }
+       if (page) {
+               int mapcount = page_mapcount(page);
+
+               if (mapcount >= 2)
+                       mss->shared_hugetlb += huge_page_size(hstate_vma(vma));
+               else
+                       mss->private_hugetlb += huge_page_size(hstate_vma(vma));
+       }
+       return 0;
+}
+#endif /* HUGETLB_PAGE */
+
 static int show_smap(struct seq_file *m, void *v, int is_pid)
 {
        struct vm_area_struct *vma = v;
        struct mem_size_stats mss;
        struct mm_walk smaps_walk = {
                .pmd_entry = smaps_pte_range,
+#ifdef CONFIG_HUGETLB_PAGE
+               .hugetlb_entry = smaps_hugetlb_range,
+#endif
                .mm = vma->vm_mm,
                .private = &mss,
        };
@@ -652,6 +686,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
                   "Referenced:     %8lu kB\n"
                   "Anonymous:      %8lu kB\n"
                   "AnonHugePages:  %8lu kB\n"
+                  "Shared_Hugetlb: %8lu kB\n"
+                  "Private_Hugetlb: %7lu kB\n"
                   "Swap:           %8lu kB\n"
                   "SwapPss:        %8lu kB\n"
                   "KernelPageSize: %8lu kB\n"
@@ -667,6 +703,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
                   mss.referenced >> 10,
                   mss.anonymous >> 10,
                   mss.anonymous_thp >> 10,
+                  mss.shared_hugetlb >> 10,
+                  mss.private_hugetlb >> 10,
                   mss.swap >> 10,
                   (unsigned long)(mss.swap_pss >> (10 + PSS_SHIFT)),
                   vma_kernel_pagesize(vma) >> 10,
@@ -754,7 +792,7 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma,
 
        if (pte_present(ptent)) {
                ptent = pte_wrprotect(ptent);
-               ptent = pte_clear_flags(ptent, _PAGE_SOFT_DIRTY);
+               ptent = pte_clear_soft_dirty(ptent);
        } else if (is_swap_pte(ptent)) {
                ptent = pte_swp_clear_soft_dirty(ptent);
        }
@@ -768,7 +806,7 @@ static inline void clear_soft_dirty_pmd(struct vm_area_struct *vma,
        pmd_t pmd = *pmdp;
 
        pmd = pmd_wrprotect(pmd);
-       pmd = pmd_clear_flags(pmd, _PAGE_SOFT_DIRTY);
+       pmd = pmd_clear_soft_dirty(pmd);
 
        if (vma->vm_flags & VM_SOFTDIRTY)
                vma->vm_flags &= ~VM_SOFTDIRTY;