The /proc/cgroups file shows the number of cgroups for each of the subsystems. With cgroup v1, the number of CSSes is the same as the number of cgroups. That is not the case anymore with cgroup v2. The /proc/cgroups file cannot show the actual number of CSSes for the subsystems that are bound to cgroup v2. So if a v2 cgroup subsystem is leaking cgroups (typically memory cgroup), we can't tell by looking at /proc/cgroups which cgroup subsystems may be responsible. This patch adds a css counter in the cgroup_subsys structure to keep track of the number of CSSes for each of the cgroup subsystems. The proc_cgroupstats_show() function is modified to show the number of CSSes instead. This will help us pinpoint which subsystem may be responsible for the increasing number of dying but still allocated cgroups. Signed-off-by: Waiman Long <longman@xxxxxxxxxx> --- include/linux/cgroup-defs.h | 3 +++ kernel/cgroup/cgroup-v1.c | 2 +- kernel/cgroup/cgroup.c | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index b36690ca0d3f..522ab77f0406 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -776,6 +776,9 @@ struct cgroup_subsys { * specifies the mask of subsystems that this one depends on. */ unsigned int depends_on; + + /* Number of CSSes, used only for /proc/cgroups */ + atomic_t nr_csses; }; extern struct percpu_rw_semaphore cgroup_threadgroup_rwsem; diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index b9dbf6bf2779..56c2b030cd00 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -678,7 +678,7 @@ int proc_cgroupstats_show(struct seq_file *m, void *v) for_each_subsys(ss, i) seq_printf(m, "%s\t%d\t%d\t%d\n", ss->legacy_name, ss->root->hierarchy_id, - atomic_read(&ss->root->nr_cgrps), + atomic_read(&ss->nr_csses), cgroup_ssid_enabled(i)); return 0; diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index c8e4b62b436a..4a818192950f 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -5375,6 +5375,7 @@ static void css_free_rwork_fn(struct work_struct *work) int id = css->id; ss->css_free(css); + atomic_dec(&ss->nr_csses); cgroup_idr_remove(&ss->css_idr, id); cgroup_put(cgrp); @@ -5567,6 +5568,7 @@ static struct cgroup_subsys_state *css_create(struct cgroup *cgrp, if (IS_ERR(css)) return css; + atomic_inc(&ss->nr_csses); init_and_link_css(css, ss, cgrp); err = percpu_ref_init(&css->refcnt, css_release, 0, GFP_KERNEL); @@ -6005,6 +6007,8 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early) /* Create the root cgroup state for this subsystem */ ss->root = &cgrp_dfl_root; css = ss->css_alloc(NULL); + atomic_set(&ss->nr_csses, 1); + /* We don't handle early failures gracefully */ BUG_ON(IS_ERR(css)); init_and_link_css(css, ss, &cgrp_dfl_root.cgrp); -- 2.39.3