mm: memcontrol: basic memory statistics in cgroup2 memory controller

Provide a cgroup2 memory.stat that provides statistics on LRU memory
and fault event counters. More consumers and breakdowns will follow.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Johannes Weiner
2016-01-20 15:03:19 -08:00
committed by Linus Torvalds
parent 44b7a8d33d
commit 587d9f726a
2 changed files with 124 additions and 0 deletions

View File

@@ -2767,6 +2767,18 @@ static unsigned long tree_stat(struct mem_cgroup *memcg,
return val;
}
static unsigned long tree_events(struct mem_cgroup *memcg,
enum mem_cgroup_events_index idx)
{
struct mem_cgroup *iter;
unsigned long val = 0;
for_each_mem_cgroup_tree(iter, memcg)
val += mem_cgroup_read_events(iter, idx);
return val;
}
static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
{
unsigned long val;
@@ -5096,6 +5108,57 @@ static int memory_events_show(struct seq_file *m, void *v)
return 0;
}
static int memory_stat_show(struct seq_file *m, void *v)
{
struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
int i;
/*
* Provide statistics on the state of the memory subsystem as
* well as cumulative event counters that show past behavior.
*
* This list is ordered following a combination of these gradients:
* 1) generic big picture -> specifics and details
* 2) reflecting userspace activity -> reflecting kernel heuristics
*
* Current memory state:
*/
seq_printf(m, "anon %llu\n",
(u64)tree_stat(memcg, MEM_CGROUP_STAT_RSS) * PAGE_SIZE);
seq_printf(m, "file %llu\n",
(u64)tree_stat(memcg, MEM_CGROUP_STAT_CACHE) * PAGE_SIZE);
seq_printf(m, "file_mapped %llu\n",
(u64)tree_stat(memcg, MEM_CGROUP_STAT_FILE_MAPPED) *
PAGE_SIZE);
seq_printf(m, "file_dirty %llu\n",
(u64)tree_stat(memcg, MEM_CGROUP_STAT_DIRTY) *
PAGE_SIZE);
seq_printf(m, "file_writeback %llu\n",
(u64)tree_stat(memcg, MEM_CGROUP_STAT_WRITEBACK) *
PAGE_SIZE);
for (i = 0; i < NR_LRU_LISTS; i++) {
struct mem_cgroup *mi;
unsigned long val = 0;
for_each_mem_cgroup_tree(mi, memcg)
val += mem_cgroup_nr_lru_pages(mi, BIT(i));
seq_printf(m, "%s %llu\n",
mem_cgroup_lru_names[i], (u64)val * PAGE_SIZE);
}
/* Accumulated memory events */
seq_printf(m, "pgfault %lu\n",
tree_events(memcg, MEM_CGROUP_EVENTS_PGFAULT));
seq_printf(m, "pgmajfault %lu\n",
tree_events(memcg, MEM_CGROUP_EVENTS_PGMAJFAULT));
return 0;
}
static struct cftype memory_files[] = {
{
.name = "current",
@@ -5126,6 +5189,11 @@ static struct cftype memory_files[] = {
.file_offset = offsetof(struct mem_cgroup, events_file),
.seq_show = memory_events_show,
},
{
.name = "stat",
.flags = CFTYPE_NOT_ON_ROOT,
.seq_show = memory_stat_show,
},
{ } /* terminate */
};