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:

committed by
Linus Torvalds

parent
44b7a8d33d
commit
587d9f726a
@@ -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 */
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user