diff options
-rw-r--r-- | include/linux/cgroup.h | 2 | ||||
-rw-r--r-- | kernel/cgroup.c | 37 |
2 files changed, 39 insertions, 0 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 3a04aeb8b5a1..9fd99f5e699f 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -910,6 +910,8 @@ void css_task_iter_end(struct css_task_iter *it); | |||
910 | int cgroup_attach_task_all(struct task_struct *from, struct task_struct *); | 910 | int cgroup_attach_task_all(struct task_struct *from, struct task_struct *); |
911 | int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from); | 911 | int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from); |
912 | 912 | ||
913 | struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgroup, | ||
914 | struct cgroup_subsys *ss); | ||
913 | struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry, | 915 | struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry, |
914 | struct cgroup_subsys *ss); | 916 | struct cgroup_subsys *ss); |
915 | 917 | ||
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 69f033582a1a..bb263d0caab3 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -277,6 +277,10 @@ static struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp, | |||
277 | if (!(cgrp->root->subsys_mask & (1 << ss->id))) | 277 | if (!(cgrp->root->subsys_mask & (1 << ss->id))) |
278 | return NULL; | 278 | return NULL; |
279 | 279 | ||
280 | /* | ||
281 | * This function is used while updating css associations and thus | ||
282 | * can't test the csses directly. Use ->child_subsys_mask. | ||
283 | */ | ||
280 | while (cgroup_parent(cgrp) && | 284 | while (cgroup_parent(cgrp) && |
281 | !(cgroup_parent(cgrp)->child_subsys_mask & (1 << ss->id))) | 285 | !(cgroup_parent(cgrp)->child_subsys_mask & (1 << ss->id))) |
282 | cgrp = cgroup_parent(cgrp); | 286 | cgrp = cgroup_parent(cgrp); |
@@ -284,6 +288,39 @@ static struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp, | |||
284 | return cgroup_css(cgrp, ss); | 288 | return cgroup_css(cgrp, ss); |
285 | } | 289 | } |
286 | 290 | ||
291 | /** | ||
292 | * cgroup_get_e_css - get a cgroup's effective css for the specified subsystem | ||
293 | * @cgrp: the cgroup of interest | ||
294 | * @ss: the subsystem of interest | ||
295 | * | ||
296 | * Find and get the effective css of @cgrp for @ss. The effective css is | ||
297 | * defined as the matching css of the nearest ancestor including self which | ||
298 | * has @ss enabled. If @ss is not mounted on the hierarchy @cgrp is on, | ||
299 | * the root css is returned, so this function always returns a valid css. | ||
300 | * The returned css must be put using css_put(). | ||
301 | */ | ||
302 | struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgrp, | ||
303 | struct cgroup_subsys *ss) | ||
304 | { | ||
305 | struct cgroup_subsys_state *css; | ||
306 | |||
307 | rcu_read_lock(); | ||
308 | |||
309 | do { | ||
310 | css = cgroup_css(cgrp, ss); | ||
311 | |||
312 | if (css && css_tryget_online(css)) | ||
313 | goto out_unlock; | ||
314 | cgrp = cgroup_parent(cgrp); | ||
315 | } while (cgrp); | ||
316 | |||
317 | css = init_css_set.subsys[ss->id]; | ||
318 | css_get(css); | ||
319 | out_unlock: | ||
320 | rcu_read_unlock(); | ||
321 | return css; | ||
322 | } | ||
323 | |||
287 | /* convenient tests for these bits */ | 324 | /* convenient tests for these bits */ |
288 | static inline bool cgroup_is_dead(const struct cgroup *cgrp) | 325 | static inline bool cgroup_is_dead(const struct cgroup *cgrp) |
289 | { | 326 | { |