mm: hugetlb: proc: add HugetlbPages field to /proc/PID/status
authorNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Fri, 6 Nov 2015 02:47:14 +0000 (18:47 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Nov 2015 03:34:48 +0000 (19:34 -0800)
Currently there's no easy way to get per-process usage of hugetlb pages,
which is inconvenient because userspace applications which use hugetlb
typically want to control their processes on the basis of how much memory
(including hugetlb) they use.  So this patch simply provides easy access
to the info via /proc/PID/status.

Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Acked-by: Joern Engel <joern@logfs.org>
Acked-by: David Rientjes <rientjes@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Documentation/filesystems/proc.txt
fs/proc/task_mmu.c
include/linux/hugetlb.h
include/linux/mm_types.h
mm/hugetlb.c
mm/rmap.c

index a7d6c06f36c4c4c5c90ba2226e26ba3dc9f3c967..12ac0e4455d4b80afc1ab5dfed0fabcd4fc55826 100644 (file)
@@ -175,6 +175,7 @@ read the file /proc/PID/status:
   VmLib:      1412 kB
   VmPTE:        20 kb
   VmSwap:        0 kB
+  HugetlbPages:          0 kB
   Threads:        1
   SigQ:   0/28578
   SigPnd: 0000000000000000
@@ -238,6 +239,7 @@ Table 1-2: Contents of the status files (as of 4.1)
  VmPTE                       size of page table entries
  VmPMD                       size of second level page tables
  VmSwap                      size of swap usage (the number of referred swapents)
+ HugetlbPages                size of hugetlb memory portions
  Threads                     number of threads
  SigQ                        number of signals queued/max. number for queue
  SigPnd                      bitmap of pending signals for the thread
index 5988b83836fb111e6929d1b67ac0a58775b0378b..288185e2476267169398576d6f6177618b5fedc9 100644 (file)
@@ -70,6 +70,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
                ptes >> 10,
                pmds >> 10,
                swap << (PAGE_SHIFT-10));
+       hugetlb_report_usage(m, mm);
 }
 
 unsigned long task_vsize(struct mm_struct *mm)
index 5e35379f58a53d09cf50bd693d0e8639c7b79709..685c262e0be848ca049ee041d00d389d3cc327fe 100644 (file)
@@ -483,6 +483,17 @@ static inline spinlock_t *huge_pte_lockptr(struct hstate *h,
 #define hugepages_supported() (HPAGE_SHIFT != 0)
 #endif
 
+void hugetlb_report_usage(struct seq_file *m, struct mm_struct *mm);
+
+static inline void hugetlb_count_add(long l, struct mm_struct *mm)
+{
+       atomic_long_add(l, &mm->hugetlb_usage);
+}
+
+static inline void hugetlb_count_sub(long l, struct mm_struct *mm)
+{
+       atomic_long_sub(l, &mm->hugetlb_usage);
+}
 #else  /* CONFIG_HUGETLB_PAGE */
 struct hstate {};
 #define alloc_huge_page(v, a, r) NULL
@@ -519,6 +530,14 @@ static inline spinlock_t *huge_pte_lockptr(struct hstate *h,
 {
        return &mm->page_table_lock;
 }
+
+static inline void hugetlb_report_usage(struct seq_file *f, struct mm_struct *m)
+{
+}
+
+static inline void hugetlb_count_sub(long l, struct mm_struct *mm)
+{
+}
 #endif /* CONFIG_HUGETLB_PAGE */
 
 static inline spinlock_t *huge_pte_lock(struct hstate *h,
index 3d6baa7d4534c68918dd7181e82674ade0b8ed98..0a85da25a8221c74bdbd8da007c2c822496b59d3 100644 (file)
@@ -486,6 +486,9 @@ struct mm_struct {
        /* address of the bounds directory */
        void __user *bd_addr;
 #endif
+#ifdef CONFIG_HUGETLB_PAGE
+       atomic_long_t hugetlb_usage;
+#endif
 };
 
 static inline void mm_init_cpumask(struct mm_struct *mm)
index 9cc773483624e4cbb1592ddde74f9c8faa21ef87..abfbe8ca3323baa668e0564567307893abc93eba 100644 (file)
@@ -2790,6 +2790,12 @@ void hugetlb_show_meminfo(void)
                                1UL << (huge_page_order(h) + PAGE_SHIFT - 10));
 }
 
+void hugetlb_report_usage(struct seq_file *m, struct mm_struct *mm)
+{
+       seq_printf(m, "HugetlbPages:\t%8lu kB\n",
+                  atomic_long_read(&mm->hugetlb_usage) << (PAGE_SHIFT - 10));
+}
+
 /* Return the number pages of memory we physically have, in PAGE_SIZE units. */
 unsigned long hugetlb_total_pages(void)
 {
@@ -3025,6 +3031,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
                        get_page(ptepage);
                        page_dup_rmap(ptepage);
                        set_huge_pte_at(dst, addr, dst_pte, entry);
+                       hugetlb_count_add(pages_per_huge_page(h), dst);
                }
                spin_unlock(src_ptl);
                spin_unlock(dst_ptl);
@@ -3105,6 +3112,7 @@ again:
                if (huge_pte_dirty(pte))
                        set_page_dirty(page);
 
+               hugetlb_count_sub(pages_per_huge_page(h), mm);
                page_remove_rmap(page);
                force_flush = !__tlb_remove_page(tlb, page);
                if (force_flush) {
@@ -3509,6 +3517,7 @@ retry:
                                && (vma->vm_flags & VM_SHARED)));
        set_huge_pte_at(mm, address, ptep, new_pte);
 
+       hugetlb_count_add(pages_per_huge_page(h), mm);
        if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED)) {
                /* Optimization, do the COW without a second fault */
                ret = hugetlb_cow(mm, vma, address, ptep, new_pte, page, ptl);
index f5b5c1f3dcd755ae313bba1404f2c9b079d5c18f..d40e7aefb888f2c9ab01ae444f52d753553af52a 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1352,7 +1352,9 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
        update_hiwater_rss(mm);
 
        if (PageHWPoison(page) && !(flags & TTU_IGNORE_HWPOISON)) {
-               if (!PageHuge(page)) {
+               if (PageHuge(page)) {
+                       hugetlb_count_sub(1 << compound_order(page), mm);
+               } else {
                        if (PageAnon(page))
                                dec_mm_counter(mm, MM_ANONPAGES);
                        else