diff options
author | Paul Menage <menage@google.com> | 2007-10-19 02:39:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 14:53:36 -0400 |
commit | 817929ec274bcfe771586d338bb31d1659615686 (patch) | |
tree | 5a96ed1afd308016e8720437a00bf2f114e907cb /include/linux | |
parent | a424316ca154317367c7ddf89997d1c80e4a8051 (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.h | 89 | ||||
-rw-r--r-- | include/linux/sched.h | 33 |
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); | |||
27 | extern void cgroup_unlock(void); | 27 | extern void cgroup_unlock(void); |
28 | extern void cgroup_fork(struct task_struct *p); | 28 | extern void cgroup_fork(struct task_struct *p); |
29 | extern void cgroup_fork_callbacks(struct task_struct *p); | 29 | extern void cgroup_fork_callbacks(struct task_struct *p); |
30 | extern void cgroup_post_fork(struct task_struct *p); | ||
30 | extern void cgroup_exit(struct task_struct *p, int run_callbacks); | 31 | extern void cgroup_exit(struct task_struct *p, int run_callbacks); |
31 | 32 | ||
32 | extern struct file_operations proc_cgroup_operations; | 33 | extern struct file_operations proc_cgroup_operations; |
33 | 34 | ||
35 | /* Define the enumeration of all cgroup subsystems */ | ||
36 | #define SUBSYS(_x) _x ## _subsys_id, | ||
37 | enum 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. */ |
35 | struct cgroup_subsys_state { | 44 | struct 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 | |||
124 | struct 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 | ||
158 | int cgroup_path(const struct cgroup *cont, char *buf, int buflen); | 213 | int cgroup_path(const struct cgroup *cont, char *buf, int buflen); |
159 | 214 | ||
160 | int __cgroup_task_count(const struct cgroup *cont); | 215 | int cgroup_task_count(const struct cgroup *cont); |
161 | static 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 */ |
171 | int cgroup_is_descendant(const struct cgroup *cont); | 218 | int cgroup_is_descendant(const struct cgroup *cont); |
@@ -213,7 +260,7 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state( | |||
213 | static inline struct cgroup_subsys_state *task_subsys_state( | 260 | static 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 | ||
219 | static inline struct cgroup* task_cgroup(struct task_struct *task, | 266 | static 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 | ||
227 | int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss); | 274 | int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss); |
228 | 275 | ||
276 | /* A cgroup_iter should be treated as an opaque object */ | ||
277 | struct 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 | */ | ||
291 | void cgroup_iter_start(struct cgroup *cont, struct cgroup_iter *it); | ||
292 | struct task_struct *cgroup_iter_next(struct cgroup *cont, | ||
293 | struct cgroup_iter *it); | ||
294 | void cgroup_iter_end(struct cgroup *cont, struct cgroup_iter *it); | ||
295 | |||
296 | |||
229 | #else /* !CONFIG_CGROUPS */ | 297 | #else /* !CONFIG_CGROUPS */ |
230 | 298 | ||
231 | static inline int cgroup_init_early(void) { return 0; } | 299 | static inline int cgroup_init_early(void) { return 0; } |
@@ -233,6 +301,7 @@ static inline int cgroup_init(void) { return 0; } | |||
233 | static inline void cgroup_init_smp(void) {} | 301 | static inline void cgroup_init_smp(void) {} |
234 | static inline void cgroup_fork(struct task_struct *p) {} | 302 | static inline void cgroup_fork(struct task_struct *p) {} |
235 | static inline void cgroup_fork_callbacks(struct task_struct *p) {} | 303 | static inline void cgroup_fork_callbacks(struct task_struct *p) {} |
304 | static inline void cgroup_post_fork(struct task_struct *p) {} | ||
236 | static inline void cgroup_exit(struct task_struct *p, int callbacks) {} | 305 | static inline void cgroup_exit(struct task_struct *p, int callbacks) {} |
237 | 306 | ||
238 | static inline void cgroup_lock(void) {} | 307 | static 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, | ||
900 | enum 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 | |||
910 | struct 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 | |||
925 | struct task_struct { | 897 | struct 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; |