mm: memcontrol: expose THP events on a per-memcg basis

Currently THP allocation events data is fairly opaque, since you can
only get it system-wide.  This patch makes it easier to reason about
transparent hugepage behaviour on a per-memcg basis.

For anonymous THP-backed pages, we already have MEMCG_RSS_HUGE in v1,
which is used for v1's rss_huge [sic].  This is reused here as it's
fairly involved to untangle NR_ANON_THPS right now to make it per-memcg,
since right now some of this is delegated to rmap before we have any
memcg actually assigned to the page.  It's a good idea to rework that,
but let's leave untangling THP allocation for a future patch.

[akpm@linux-foundation.org: fix build]
[chris@chrisdown.name: fix memcontrol build when THP is disabled]
  Link: http://lkml.kernel.org/r/20190131160802.GA5777@chrisdown.name
Link: http://lkml.kernel.org/r/20190129205852.GA7310@chrisdown.name
Signed-off-by: Chris Down <chris@chrisdown.name>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: Tejun Heo <tj@kernel.org>
Cc: Roman Gushchin <guro@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Chris Down 2019-03-05 15:48:09 -08:00 committed by Linus Torvalds
parent 2bb0f34fe3
commit 1ff9e6e179
4 changed files with 36 additions and 0 deletions

View file

@ -1189,6 +1189,10 @@ PAGE_SIZE multiple when read back.
Amount of cached filesystem data that was modified and Amount of cached filesystem data that was modified and
is currently being written back to disk is currently being written back to disk
anon_thp
Amount of memory used in anonymous mappings backed by
transparent hugepages
inactive_anon, active_anon, inactive_file, active_file, unevictable inactive_anon, active_anon, inactive_file, active_file, unevictable
Amount of memory, swap-backed and filesystem-backed, Amount of memory, swap-backed and filesystem-backed,
on the internal memory management lists used by the on the internal memory management lists used by the
@ -1248,6 +1252,18 @@ PAGE_SIZE multiple when read back.
Amount of reclaimed lazyfree pages Amount of reclaimed lazyfree pages
thp_fault_alloc
Number of transparent hugepages which were allocated to satisfy
a page fault, including COW faults. This counter is not present
when CONFIG_TRANSPARENT_HUGEPAGE is not set.
thp_collapse_alloc
Number of transparent hugepages which were allocated to allow
collapsing an existing range of pages. This counter is not
present when CONFIG_TRANSPARENT_HUGEPAGE is not set.
memory.swap.current memory.swap.current
A read-only single value file which exists on non-root A read-only single value file which exists on non-root
cgroups. cgroups.

View file

@ -617,6 +617,7 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
mm_inc_nr_ptes(vma->vm_mm); mm_inc_nr_ptes(vma->vm_mm);
spin_unlock(vmf->ptl); spin_unlock(vmf->ptl);
count_vm_event(THP_FAULT_ALLOC); count_vm_event(THP_FAULT_ALLOC);
count_memcg_events(memcg, THP_FAULT_ALLOC, 1);
} }
return 0; return 0;
@ -1338,6 +1339,7 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
} }
count_vm_event(THP_FAULT_ALLOC); count_vm_event(THP_FAULT_ALLOC);
count_memcg_events(memcg, THP_FAULT_ALLOC, 1);
if (!page) if (!page)
clear_huge_page(new_page, vmf->address, HPAGE_PMD_NR); clear_huge_page(new_page, vmf->address, HPAGE_PMD_NR);

View file

@ -1074,6 +1074,7 @@ static void collapse_huge_page(struct mm_struct *mm,
BUG_ON(!pmd_none(*pmd)); BUG_ON(!pmd_none(*pmd));
page_add_new_anon_rmap(new_page, vma, address, true); page_add_new_anon_rmap(new_page, vma, address, true);
mem_cgroup_commit_charge(new_page, memcg, false, true); mem_cgroup_commit_charge(new_page, memcg, false, true);
count_memcg_events(memcg, THP_COLLAPSE_ALLOC, 1);
lru_cache_add_active_or_unevictable(new_page, vma); lru_cache_add_active_or_unevictable(new_page, vma);
pgtable_trans_huge_deposit(mm, pmd, pgtable); pgtable_trans_huge_deposit(mm, pmd, pgtable);
set_pmd_at(mm, address, pmd, _pmd); set_pmd_at(mm, address, pmd, _pmd);
@ -1502,6 +1503,7 @@ static void collapse_shmem(struct mm_struct *mm,
page_ref_add(new_page, HPAGE_PMD_NR - 1); page_ref_add(new_page, HPAGE_PMD_NR - 1);
set_page_dirty(new_page); set_page_dirty(new_page);
mem_cgroup_commit_charge(new_page, memcg, false, true); mem_cgroup_commit_charge(new_page, memcg, false, true);
count_memcg_events(memcg, THP_COLLAPSE_ALLOC, 1);
lru_cache_add_anon(new_page); lru_cache_add_anon(new_page);
/* /*

View file

@ -39,6 +39,7 @@
#include <linux/shmem_fs.h> #include <linux/shmem_fs.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/vm_event_item.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/page-flags.h> #include <linux/page-flags.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
@ -5571,6 +5572,15 @@ static int memory_stat_show(struct seq_file *m, void *v)
seq_printf(m, "file_writeback %llu\n", seq_printf(m, "file_writeback %llu\n",
(u64)acc.stat[NR_WRITEBACK] * PAGE_SIZE); (u64)acc.stat[NR_WRITEBACK] * PAGE_SIZE);
/*
* TODO: We should eventually replace our own MEMCG_RSS_HUGE counter
* with the NR_ANON_THP vm counter, but right now it's a pain in the
* arse because it requires migrating the work out of rmap to a place
* where the page->mem_cgroup is set up and stable.
*/
seq_printf(m, "anon_thp %llu\n",
(u64)acc.stat[MEMCG_RSS_HUGE] * PAGE_SIZE);
for (i = 0; i < NR_LRU_LISTS; i++) for (i = 0; i < NR_LRU_LISTS; i++)
seq_printf(m, "%s %llu\n", mem_cgroup_lru_names[i], seq_printf(m, "%s %llu\n", mem_cgroup_lru_names[i],
(u64)acc.lru_pages[i] * PAGE_SIZE); (u64)acc.lru_pages[i] * PAGE_SIZE);
@ -5602,6 +5612,12 @@ static int memory_stat_show(struct seq_file *m, void *v)
seq_printf(m, "pglazyfree %lu\n", acc.events[PGLAZYFREE]); seq_printf(m, "pglazyfree %lu\n", acc.events[PGLAZYFREE]);
seq_printf(m, "pglazyfreed %lu\n", acc.events[PGLAZYFREED]); seq_printf(m, "pglazyfreed %lu\n", acc.events[PGLAZYFREED]);
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
seq_printf(m, "thp_fault_alloc %lu\n", acc.events[THP_FAULT_ALLOC]);
seq_printf(m, "thp_collapse_alloc %lu\n",
acc.events[THP_COLLAPSE_ALLOC]);
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
return 0; return 0;
} }