diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3ede56d6b3073c8e6f3b1afa24fe64ddb926b285..1938e69ad5cc3fae15d8f09dbd397684bebcfd24 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4556,6 +4556,53 @@ static void mem_cgroup_oom_unregister_event(struct mem_cgroup *memcg, spin_unlock(&memcg_oom_lock); } +static const char *const memcg_flag_name[] = { + "NO_REF", + "ONLINE", + "RELEASED", + "VISIBLE", + "DYING" +}; + +static void memcg_flag_stat_get(int mem_flags, int *stat) +{ + int i; + int flags = mem_flags; + + for (i = 0; i < ARRAY_SIZE(memcg_flag_name); i++) { + if (flags & 1) + stat[i] += 1; + flags >>= 1; + } +} + +static int memcg_flag_stat_show(struct seq_file *sf, void *v) +{ + int self_flag[ARRAY_SIZE(memcg_flag_name)]; + int child_flag[ARRAY_SIZE(memcg_flag_name)]; + int iter; + struct cgroup_subsys_state *child; + struct cgroup_subsys_state *css = seq_css(sf); + + memset(self_flag, 0, sizeof(self_flag)); + memset(child_flag, 0, sizeof(child_flag)); + + memcg_flag_stat_get(css->flags, self_flag); + + rcu_read_lock(); + css_for_each_child(child, css) + memcg_flag_stat_get(child->flags, child_flag); + rcu_read_unlock(); + + for (iter = 0; iter < ARRAY_SIZE(memcg_flag_name); iter++) + seq_printf(sf, "%s %d\n", memcg_flag_name[iter], self_flag[iter]); + + for (iter = 0; iter < ARRAY_SIZE(memcg_flag_name); iter++) + seq_printf(sf, "CHILD_%s %d\n", memcg_flag_name[iter], child_flag[iter]); + + return 0; +} + static int mem_cgroup_oom_control_read(struct seq_file *sf, void *v) { struct mem_cgroup *memcg = mem_cgroup_from_seq(sf); @@ -5259,6 +5306,10 @@ static struct cftype mem_cgroup_legacy_files[] = { .write_u64 = mem_cgroup_oom_control_write, .private = MEMFILE_PRIVATE(_OOM_TYPE, OOM_CONTROL), }, + { + .name = "flag_stat", + .seq_show = memcg_flag_stat_show, + }, { .name = "pressure_level", },