[RFC 4/5] cpuacct: do not gather cpuacct statistics when not mounted

Glauber Costa
2012-09-04T14:22:38Z

Currently, the only test that prevents us from running the expensive
cpuacct_charge() is cpuacct_subsys.active == true. This will hold at all
times after the subsystem is activated, even if it is not mounted.

IOW, use it or not, you pay it. By hooking with the bind() callback, we
can detect when cpuacct is mounted or umounted, and stop collecting
statistics when this cgroup is not in use.

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: Dave Jones <davej@redhat.com>
CC: Ben Hutchings <ben@decadent.org.uk>
CC: Peter Zijlstra <a.p.zijlstra@chello.nl>
CC: Paul Turner <pjt@google.com>
CC: Lennart Poettering <lennart@poettering.net>
CC: Kay Sievers <kay.sievers@vrfy.org>
CC: Tejun Heo <tj@kernel.org>
---
kernel/sched/core.c | 8 ++++++++
kernel/sched/sched.h | 3 +++
2 files changed, 11 insertions(+)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index e46871d..d654bd1 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8595,6 +8595,13 @@ static struct cftype files[] = {
{ } /* terminate */
};

+bool cpuacct_mounted;
+
+void cpuacct_bind(struct cgroup *root)
+{
+ cpuacct_mounted = root->root == root_cpuacct.css.cgroup->root;
+}
+
/*
* charge this task's execution time to its accounting group.
*
@@ -8628,6 +8635,7 @@ struct cgroup_subsys cpuacct_subsys = {
.destroy = cpuacct_destroy,
.subsys_id = cpuacct_subsys_id,
.base_cftypes = files,
+ .bind = cpuacct_bind,
#ifdef CONFIG_CGROUP_FORCE_COMOUNT_CPU
.comounts = 1,
.must_comount = { cpu_cgroup_subsys_id, },
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 1da9fa8..d33f777 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -887,6 +887,7 @@ extern void update_idle_cpu_load(struct rq *this_rq);
#include <linux/cgroup.h>

extern bool cpuacct_from_cpu;
+extern bool cpuacct_mounted;

/* track cpu usage of a group of tasks and its child groups */
struct cpuacct {
@@ -921,6 +922,8 @@ extern void __cpuacct_charge(struct task_struct *tsk, u64 cputime);

static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime)
{
+ if (unlikely(!cpuacct_mounted))
+ return;
#ifdef CONFIG_CGROUP_FORCE_COMOUNT_CPU
if (likely(!cpuacct_from_cpu))
return;
--
1.7.11.4