aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Morton <akpm@linux-foundation.org>2007-11-14 19:59:45 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-14 21:45:40 -0500
commitcfb5285660aad4931b2ebbfa902ea48a37dfffa1 (patch)
tree6c345c4f00a139d7ccbc4efc5f2b9829aec21d24
parent45c682a68a87251d9a01383ce076ab21ee09812e (diff)
revert "Task Control Groups: example CPU accounting subsystem"
Revert 62d0df64065e7c135d0002f069444fbdfc64768f. This was originally intended as a simple initial example of how to create a control groups subsystem; it wasn't intended for mainline, but I didn't make this clear enough to Andrew. The CFS cgroup subsystem now has better functionality for the per-cgroup usage accounting (based directly on CFS stats) than the "usage" status file in this patch, and the "load" status file is rather simplistic - although having a per-cgroup load average report would be a useful feature, I don't believe this patch actually provides it. If it gets into the final 2.6.24 we'd probably have to support this interface for ever. Cc: Paul Menage <menage@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/cgroup_subsys.h6
-rw-r--r--include/linux/cpu_acct.h14
-rw-r--r--init/Kconfig7
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/cpu_acct.c186
-rw-r--r--kernel/sched.c14
6 files changed, 3 insertions, 225 deletions
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index 0b9bfbde8168..d62fcee9a08a 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -13,12 +13,6 @@ SUBSYS(cpuset)
13 13
14/* */ 14/* */
15 15
16#ifdef CONFIG_CGROUP_CPUACCT
17SUBSYS(cpuacct)
18#endif
19
20/* */
21
22#ifdef CONFIG_CGROUP_DEBUG 16#ifdef CONFIG_CGROUP_DEBUG
23SUBSYS(debug) 17SUBSYS(debug)
24#endif 18#endif
diff --git a/include/linux/cpu_acct.h b/include/linux/cpu_acct.h
deleted file mode 100644
index 6b5fd8a66c8d..000000000000
--- a/include/linux/cpu_acct.h
+++ /dev/null
@@ -1,14 +0,0 @@
1
2#ifndef _LINUX_CPU_ACCT_H
3#define _LINUX_CPU_ACCT_H
4
5#include <linux/cgroup.h>
6#include <asm/cputime.h>
7
8#ifdef CONFIG_CGROUP_CPUACCT
9extern void cpuacct_charge(struct task_struct *, cputime_t cputime);
10#else
11static void inline cpuacct_charge(struct task_struct *p, cputime_t cputime) {}
12#endif
13
14#endif
diff --git a/init/Kconfig b/init/Kconfig
index 8b88d0bedcbd..5b92e3aa1366 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -301,13 +301,6 @@ config CGROUP_NS
301 for instance virtual servers and checkpoint/restart 301 for instance virtual servers and checkpoint/restart
302 jobs. 302 jobs.
303 303
304config CGROUP_CPUACCT
305 bool "Simple CPU accounting cgroup subsystem"
306 depends on CGROUPS
307 help
308 Provides a simple Resource Controller for monitoring the
309 total CPU consumed by the tasks in a cgroup
310
311config CPUSETS 304config CPUSETS
312 bool "Cpuset support" 305 bool "Cpuset support"
313 depends on SMP && CGROUPS 306 depends on SMP && CGROUPS
diff --git a/kernel/Makefile b/kernel/Makefile
index f60afe742599..dfa96956dae0 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -40,7 +40,6 @@ obj-$(CONFIG_COMPAT) += compat.o
40obj-$(CONFIG_CGROUPS) += cgroup.o 40obj-$(CONFIG_CGROUPS) += cgroup.o
41obj-$(CONFIG_CGROUP_DEBUG) += cgroup_debug.o 41obj-$(CONFIG_CGROUP_DEBUG) += cgroup_debug.o
42obj-$(CONFIG_CPUSETS) += cpuset.o 42obj-$(CONFIG_CPUSETS) += cpuset.o
43obj-$(CONFIG_CGROUP_CPUACCT) += cpu_acct.o
44obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o 43obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o
45obj-$(CONFIG_IKCONFIG) += configs.o 44obj-$(CONFIG_IKCONFIG) += configs.o
46obj-$(CONFIG_STOP_MACHINE) += stop_machine.o 45obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
diff --git a/kernel/cpu_acct.c b/kernel/cpu_acct.c
deleted file mode 100644
index 731e47e7f164..000000000000
--- a/kernel/cpu_acct.c
+++ /dev/null
@@ -1,186 +0,0 @@
1/*
2 * kernel/cpu_acct.c - CPU accounting cgroup subsystem
3 *
4 * Copyright (C) Google Inc, 2006
5 *
6 * Developed by Paul Menage (menage@google.com) and Balbir Singh
7 * (balbir@in.ibm.com)
8 *
9 */
10
11/*
12 * Example cgroup subsystem for reporting total CPU usage of tasks in a
13 * cgroup, along with percentage load over a time interval
14 */
15
16#include <linux/module.h>
17#include <linux/cgroup.h>
18#include <linux/fs.h>
19#include <linux/rcupdate.h>
20
21#include <asm/div64.h>
22
23struct cpuacct {
24 struct cgroup_subsys_state css;
25 spinlock_t lock;
26 /* total time used by this class */
27 cputime64_t time;
28
29 /* time when next load calculation occurs */
30 u64 next_interval_check;
31
32 /* time used in current period */
33 cputime64_t current_interval_time;
34
35 /* time used in last period */
36 cputime64_t last_interval_time;
37};
38
39struct cgroup_subsys cpuacct_subsys;
40
41static inline struct cpuacct *cgroup_ca(struct cgroup *cont)
42{
43 return container_of(cgroup_subsys_state(cont, cpuacct_subsys_id),
44 struct cpuacct, css);
45}
46
47static inline struct cpuacct *task_ca(struct task_struct *task)
48{
49 return container_of(task_subsys_state(task, cpuacct_subsys_id),
50 struct cpuacct, css);
51}
52
53#define INTERVAL (HZ * 10)
54
55static inline u64 next_interval_boundary(u64 now)
56{
57 /* calculate the next interval boundary beyond the
58 * current time */
59 do_div(now, INTERVAL);
60 return (now + 1) * INTERVAL;
61}
62
63static struct cgroup_subsys_state *cpuacct_create(
64 struct cgroup_subsys *ss, struct cgroup *cont)
65{
66 struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
67
68 if (!ca)
69 return ERR_PTR(-ENOMEM);
70 spin_lock_init(&ca->lock);
71 ca->next_interval_check = next_interval_boundary(get_jiffies_64());
72 return &ca->css;
73}
74
75static void cpuacct_destroy(struct cgroup_subsys *ss,
76 struct cgroup *cont)
77{
78 kfree(cgroup_ca(cont));
79}
80
81/* Lazily update the load calculation if necessary. Called with ca locked */
82static void cpuusage_update(struct cpuacct *ca)
83{
84 u64 now = get_jiffies_64();
85
86 /* If we're not due for an update, return */
87 if (ca->next_interval_check > now)
88 return;
89
90 if (ca->next_interval_check <= (now - INTERVAL)) {
91 /* If it's been more than an interval since the last
92 * check, then catch up - the last interval must have
93 * been zero load */
94 ca->last_interval_time = 0;
95 ca->next_interval_check = next_interval_boundary(now);
96 } else {
97 /* If a steal takes the last interval time negative,
98 * then we just ignore it */
99 if ((s64)ca->current_interval_time > 0)
100 ca->last_interval_time = ca->current_interval_time;
101 else
102 ca->last_interval_time = 0;
103 ca->next_interval_check += INTERVAL;
104 }
105 ca->current_interval_time = 0;
106}
107
108static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
109{
110 struct cpuacct *ca = cgroup_ca(cont);
111 u64 time;
112
113 spin_lock_irq(&ca->lock);
114 cpuusage_update(ca);
115 time = cputime64_to_jiffies64(ca->time);
116 spin_unlock_irq(&ca->lock);
117
118 /* Convert 64-bit jiffies to seconds */
119 time *= 1000;
120 do_div(time, HZ);
121 return time;
122}
123
124static u64 load_read(struct cgroup *cont, struct cftype *cft)
125{
126 struct cpuacct *ca = cgroup_ca(cont);
127 u64 time;
128
129 /* Find the time used in the previous interval */
130 spin_lock_irq(&ca->lock);
131 cpuusage_update(ca);
132 time = cputime64_to_jiffies64(ca->last_interval_time);
133 spin_unlock_irq(&ca->lock);
134
135 /* Convert time to a percentage, to give the load in the
136 * previous period */
137 time *= 100;
138 do_div(time, INTERVAL);
139
140 return time;
141}
142
143static struct cftype files[] = {
144 {
145 .name = "usage",
146 .read_uint = cpuusage_read,
147 },
148 {
149 .name = "load",
150 .read_uint = load_read,
151 }
152};
153
154static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cont)
155{
156 return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
157}
158
159void cpuacct_charge(struct task_struct *task, cputime_t cputime)
160{
161
162 struct cpuacct *ca;
163 unsigned long flags;
164
165 if (!cpuacct_subsys.active)
166 return;
167 rcu_read_lock();
168 ca = task_ca(task);
169 if (ca) {
170 spin_lock_irqsave(&ca->lock, flags);
171 cpuusage_update(ca);
172 ca->time = cputime64_add(ca->time, cputime);
173 ca->current_interval_time =
174 cputime64_add(ca->current_interval_time, cputime);
175 spin_unlock_irqrestore(&ca->lock, flags);
176 }
177 rcu_read_unlock();
178}
179
180struct cgroup_subsys cpuacct_subsys = {
181 .name = "cpuacct",
182 .create = cpuacct_create,
183 .destroy = cpuacct_destroy,
184 .populate = cpuacct_populate,
185 .subsys_id = cpuacct_subsys_id,
186};
diff --git a/kernel/sched.c b/kernel/sched.c
index b18f231a4875..4fb3532dd7e8 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -52,7 +52,6 @@
52#include <linux/cpu.h> 52#include <linux/cpu.h>
53#include <linux/cpuset.h> 53#include <linux/cpuset.h>
54#include <linux/percpu.h> 54#include <linux/percpu.h>
55#include <linux/cpu_acct.h>
56#include <linux/kthread.h> 55#include <linux/kthread.h>
57#include <linux/seq_file.h> 56#include <linux/seq_file.h>
58#include <linux/sysctl.h> 57#include <linux/sysctl.h>
@@ -3338,13 +3337,9 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
3338{ 3337{
3339 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 3338 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
3340 cputime64_t tmp; 3339 cputime64_t tmp;
3341 struct rq *rq = this_rq();
3342 3340
3343 p->utime = cputime_add(p->utime, cputime); 3341 p->utime = cputime_add(p->utime, cputime);
3344 3342
3345 if (p != rq->idle)
3346 cpuacct_charge(p, cputime);
3347
3348 /* Add user time to cpustat. */ 3343 /* Add user time to cpustat. */
3349 tmp = cputime_to_cputime64(cputime); 3344 tmp = cputime_to_cputime64(cputime);
3350 if (TASK_NICE(p) > 0) 3345 if (TASK_NICE(p) > 0)
@@ -3408,10 +3403,9 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
3408 cpustat->irq = cputime64_add(cpustat->irq, tmp); 3403 cpustat->irq = cputime64_add(cpustat->irq, tmp);
3409 else if (softirq_count()) 3404 else if (softirq_count())
3410 cpustat->softirq = cputime64_add(cpustat->softirq, tmp); 3405 cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
3411 else if (p != rq->idle) { 3406 else if (p != rq->idle)
3412 cpustat->system = cputime64_add(cpustat->system, tmp); 3407 cpustat->system = cputime64_add(cpustat->system, tmp);
3413 cpuacct_charge(p, cputime); 3408 else if (atomic_read(&rq->nr_iowait) > 0)
3414 } else if (atomic_read(&rq->nr_iowait) > 0)
3415 cpustat->iowait = cputime64_add(cpustat->iowait, tmp); 3409 cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
3416 else 3410 else
3417 cpustat->idle = cputime64_add(cpustat->idle, tmp); 3411 cpustat->idle = cputime64_add(cpustat->idle, tmp);
@@ -3447,10 +3441,8 @@ void account_steal_time(struct task_struct *p, cputime_t steal)
3447 cpustat->iowait = cputime64_add(cpustat->iowait, tmp); 3441 cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
3448 else 3442 else
3449 cpustat->idle = cputime64_add(cpustat->idle, tmp); 3443 cpustat->idle = cputime64_add(cpustat->idle, tmp);
3450 } else { 3444 } else
3451 cpustat->steal = cputime64_add(cpustat->steal, tmp); 3445 cpustat->steal = cputime64_add(cpustat->steal, tmp);
3452 cpuacct_charge(p, -tmp);
3453 }
3454} 3446}
3455 3447
3456/* 3448/*