aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorPaul Menage <menage@google.com>2007-10-19 02:39:36 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:36 -0400
commit817929ec274bcfe771586d338bb31d1659615686 (patch)
tree5a96ed1afd308016e8720437a00bf2f114e907cb /include/linux
parenta424316ca154317367c7ddf89997d1c80e4a8051 (diff)
Task Control Groups: shared cgroup subsystem group arrays
Replace the struct css_set embedded in task_struct with a pointer; all tasks that have the same set of memberships across all hierarchies will share a css_set object, and will be linked via their css_sets field to the "tasks" list_head in the css_set. Assuming that many tasks share the same cgroup assignments, this reduces overall space usage and keeps the size of the task_struct down (three pointers added to task_struct compared to a non-cgroups kernel, no matter how many subsystems are registered). [akpm@linux-foundation.org: fix a printk] [akpm@linux-foundation.org: build fix] Signed-off-by: Paul Menage <menage@google.com> Cc: Serge E. Hallyn <serue@us.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Dave Hansen <haveblue@us.ibm.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Paul Jackson <pj@sgi.com> Cc: Kirill Korotaev <dev@openvz.org> Cc: Herbert Poetzl <herbert@13thfloor.at> Cc: Srivatsa Vaddagiri <vatsa@in.ibm.com> Cc: Cedric Le Goater <clg@fr.ibm.com> Cc: Serge E. Hallyn <serue@us.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Dave Hansen <haveblue@us.ibm.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Paul Jackson <pj@sgi.com> Cc: Kirill Korotaev <dev@openvz.org> Cc: Herbert Poetzl <herbert@13thfloor.at> Cc: Srivatsa Vaddagiri <vatsa@in.ibm.com> Cc: Cedric Le Goater <clg@fr.ibm.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/cgroup.h89
-rw-r--r--include/linux/sched.h33
2 files changed, 83 insertions, 39 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index a9553568118f..836b3557bb76 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -27,10 +27,19 @@ extern void cgroup_lock(void);
27extern void cgroup_unlock(void); 27extern void cgroup_unlock(void);
28extern void cgroup_fork(struct task_struct *p); 28extern void cgroup_fork(struct task_struct *p);
29extern void cgroup_fork_callbacks(struct task_struct *p); 29extern void cgroup_fork_callbacks(struct task_struct *p);
30extern void cgroup_post_fork(struct task_struct *p);
30extern void cgroup_exit(struct task_struct *p, int run_callbacks); 31extern void cgroup_exit(struct task_struct *p, int run_callbacks);
31 32
32extern struct file_operations proc_cgroup_operations; 33extern struct file_operations proc_cgroup_operations;
33 34
35/* Define the enumeration of all cgroup subsystems */
36#define SUBSYS(_x) _x ## _subsys_id,
37enum cgroup_subsys_id {
38#include <linux/cgroup_subsys.h>
39 CGROUP_SUBSYS_COUNT
40};
41#undef SUBSYS
42
34/* Per-subsystem/per-cgroup state maintained by the system. */ 43/* Per-subsystem/per-cgroup state maintained by the system. */
35struct cgroup_subsys_state { 44struct cgroup_subsys_state {
36 /* The cgroup that this subsystem is attached to. Useful 45 /* The cgroup that this subsystem is attached to. Useful
@@ -97,6 +106,52 @@ struct cgroup {
97 106
98 struct cgroupfs_root *root; 107 struct cgroupfs_root *root;
99 struct cgroup *top_cgroup; 108 struct cgroup *top_cgroup;
109
110 /*
111 * List of cg_cgroup_links pointing at css_sets with
112 * tasks in this cgroup. Protected by css_set_lock
113 */
114 struct list_head css_sets;
115};
116
117/* A css_set is a structure holding pointers to a set of
118 * cgroup_subsys_state objects. This saves space in the task struct
119 * object and speeds up fork()/exit(), since a single inc/dec and a
120 * list_add()/del() can bump the reference count on the entire
121 * cgroup set for a task.
122 */
123
124struct css_set {
125
126 /* Reference count */
127 struct kref ref;
128
129 /*
130 * List running through all cgroup groups. Protected by
131 * css_set_lock
132 */
133 struct list_head list;
134
135 /*
136 * List running through all tasks using this cgroup
137 * group. Protected by css_set_lock
138 */
139 struct list_head tasks;
140
141 /*
142 * List of cg_cgroup_link objects on link chains from
143 * cgroups referenced from this css_set. Protected by
144 * css_set_lock
145 */
146 struct list_head cg_links;
147
148 /*
149 * Set of subsystem states, one for each subsystem. This array
150 * is immutable after creation apart from the init_css_set
151 * during subsystem registration (at boot time).
152 */
153 struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
154
100}; 155};
101 156
102/* struct cftype: 157/* struct cftype:
@@ -157,15 +212,7 @@ int cgroup_is_removed(const struct cgroup *cont);
157 212
158int cgroup_path(const struct cgroup *cont, char *buf, int buflen); 213int cgroup_path(const struct cgroup *cont, char *buf, int buflen);
159 214
160int __cgroup_task_count(const struct cgroup *cont); 215int cgroup_task_count(const struct cgroup *cont);
161static inline int cgroup_task_count(const struct cgroup *cont)
162{
163 int task_count;
164 rcu_read_lock();
165 task_count = __cgroup_task_count(cont);
166 rcu_read_unlock();
167 return task_count;
168}
169 216
170/* Return true if the cgroup is a descendant of the current cgroup */ 217/* Return true if the cgroup is a descendant of the current cgroup */
171int cgroup_is_descendant(const struct cgroup *cont); 218int cgroup_is_descendant(const struct cgroup *cont);
@@ -213,7 +260,7 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state(
213static inline struct cgroup_subsys_state *task_subsys_state( 260static inline struct cgroup_subsys_state *task_subsys_state(
214 struct task_struct *task, int subsys_id) 261 struct task_struct *task, int subsys_id)
215{ 262{
216 return rcu_dereference(task->cgroups.subsys[subsys_id]); 263 return rcu_dereference(task->cgroups->subsys[subsys_id]);
217} 264}
218 265
219static inline struct cgroup* task_cgroup(struct task_struct *task, 266static inline struct cgroup* task_cgroup(struct task_struct *task,
@@ -226,6 +273,27 @@ int cgroup_path(const struct cgroup *cont, char *buf, int buflen);
226 273
227int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss); 274int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss);
228 275
276/* A cgroup_iter should be treated as an opaque object */
277struct cgroup_iter {
278 struct list_head *cg_link;
279 struct list_head *task;
280};
281
282/* To iterate across the tasks in a cgroup:
283 *
284 * 1) call cgroup_iter_start to intialize an iterator
285 *
286 * 2) call cgroup_iter_next() to retrieve member tasks until it
287 * returns NULL or until you want to end the iteration
288 *
289 * 3) call cgroup_iter_end() to destroy the iterator.
290 */
291void cgroup_iter_start(struct cgroup *cont, struct cgroup_iter *it);
292struct task_struct *cgroup_iter_next(struct cgroup *cont,
293 struct cgroup_iter *it);
294void cgroup_iter_end(struct cgroup *cont, struct cgroup_iter *it);
295
296
229#else /* !CONFIG_CGROUPS */ 297#else /* !CONFIG_CGROUPS */
230 298
231static inline int cgroup_init_early(void) { return 0; } 299static inline int cgroup_init_early(void) { return 0; }
@@ -233,6 +301,7 @@ static inline int cgroup_init(void) { return 0; }
233static inline void cgroup_init_smp(void) {} 301static inline void cgroup_init_smp(void) {}
234static inline void cgroup_fork(struct task_struct *p) {} 302static inline void cgroup_fork(struct task_struct *p) {}
235static inline void cgroup_fork_callbacks(struct task_struct *p) {} 303static inline void cgroup_fork_callbacks(struct task_struct *p) {}
304static inline void cgroup_post_fork(struct task_struct *p) {}
236static inline void cgroup_exit(struct task_struct *p, int callbacks) {} 305static inline void cgroup_exit(struct task_struct *p, int callbacks) {}
237 306
238static inline void cgroup_lock(void) {} 307static inline void cgroup_lock(void) {}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index af2ed4bae678..1aa1cfa63b37 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -894,34 +894,6 @@ struct sched_entity {
894#endif 894#endif
895}; 895};
896 896
897#ifdef CONFIG_CGROUPS
898
899#define SUBSYS(_x) _x ## _subsys_id,
900enum cgroup_subsys_id {
901#include <linux/cgroup_subsys.h>
902 CGROUP_SUBSYS_COUNT
903};
904#undef SUBSYS
905
906/* A css_set is a structure holding pointers to a set of
907 * cgroup_subsys_state objects.
908 */
909
910struct css_set {
911
912 /* Set of subsystem states, one for each subsystem. NULL for
913 * subsystems that aren't part of this hierarchy. These
914 * pointers reduce the number of dereferences required to get
915 * from a task to its state for a given cgroup, but result
916 * in increased space usage if tasks are in wildly different
917 * groupings across different hierarchies. This array is
918 * immutable after creation */
919 struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
920
921};
922
923#endif /* CONFIG_CGROUPS */
924
925struct task_struct { 897struct task_struct {
926 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ 898 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
927 void *stack; 899 void *stack;
@@ -1159,7 +1131,10 @@ struct task_struct {
1159 int cpuset_mem_spread_rotor; 1131 int cpuset_mem_spread_rotor;
1160#endif 1132#endif
1161#ifdef CONFIG_CGROUPS 1133#ifdef CONFIG_CGROUPS
1162 struct css_set cgroups; 1134 /* Control Group info protected by css_set_lock */
1135 struct css_set *cgroups;
1136 /* cg_list protected by css_set_lock and tsk->alloc_lock */
1137 struct list_head cg_list;
1163#endif 1138#endif
1164#ifdef CONFIG_FUTEX 1139#ifdef CONFIG_FUTEX
1165 struct robust_list_head __user *robust_list; 1140 struct robust_list_head __user *robust_list;