aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c67
1 files changed, 52 insertions, 15 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index e2769e13980c..3ac6f5b0a64b 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1646,7 +1646,9 @@ static inline struct cftype *__d_cft(struct dentry *dentry)
1646int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) 1646int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
1647{ 1647{
1648 char *start; 1648 char *start;
1649 struct dentry *dentry = rcu_dereference(cgrp->dentry); 1649 struct dentry *dentry = rcu_dereference_check(cgrp->dentry,
1650 rcu_read_lock_held() ||
1651 cgroup_lock_is_held());
1650 1652
1651 if (!dentry || cgrp == dummytop) { 1653 if (!dentry || cgrp == dummytop) {
1652 /* 1654 /*
@@ -1662,13 +1664,17 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
1662 *--start = '\0'; 1664 *--start = '\0';
1663 for (;;) { 1665 for (;;) {
1664 int len = dentry->d_name.len; 1666 int len = dentry->d_name.len;
1667
1665 if ((start -= len) < buf) 1668 if ((start -= len) < buf)
1666 return -ENAMETOOLONG; 1669 return -ENAMETOOLONG;
1667 memcpy(start, cgrp->dentry->d_name.name, len); 1670 memcpy(start, dentry->d_name.name, len);
1668 cgrp = cgrp->parent; 1671 cgrp = cgrp->parent;
1669 if (!cgrp) 1672 if (!cgrp)
1670 break; 1673 break;
1671 dentry = rcu_dereference(cgrp->dentry); 1674
1675 dentry = rcu_dereference_check(cgrp->dentry,
1676 rcu_read_lock_held() ||
1677 cgroup_lock_is_held());
1672 if (!cgrp->parent) 1678 if (!cgrp->parent)
1673 continue; 1679 continue;
1674 if (--start < buf) 1680 if (--start < buf)
@@ -2988,7 +2994,6 @@ static void cgroup_event_remove(struct work_struct *work)
2988 remove); 2994 remove);
2989 struct cgroup *cgrp = event->cgrp; 2995 struct cgroup *cgrp = event->cgrp;
2990 2996
2991 /* TODO: check return code */
2992 event->cft->unregister_event(cgrp, event->cft, event->eventfd); 2997 event->cft->unregister_event(cgrp, event->cft, event->eventfd);
2993 2998
2994 eventfd_ctx_put(event->eventfd); 2999 eventfd_ctx_put(event->eventfd);
@@ -3010,7 +3015,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
3010 unsigned long flags = (unsigned long)key; 3015 unsigned long flags = (unsigned long)key;
3011 3016
3012 if (flags & POLLHUP) { 3017 if (flags & POLLHUP) {
3013 remove_wait_queue_locked(event->wqh, &event->wait); 3018 __remove_wait_queue(event->wqh, &event->wait);
3014 spin_lock(&cgrp->event_list_lock); 3019 spin_lock(&cgrp->event_list_lock);
3015 list_del(&event->list); 3020 list_del(&event->list);
3016 spin_unlock(&cgrp->event_list_lock); 3021 spin_unlock(&cgrp->event_list_lock);
@@ -3609,7 +3614,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
3609 * @ss: the subsystem to load 3614 * @ss: the subsystem to load
3610 * 3615 *
3611 * This function should be called in a modular subsystem's initcall. If the 3616 * This function should be called in a modular subsystem's initcall. If the
3612 * subsytem is built as a module, it will be assigned a new subsys_id and set 3617 * subsystem is built as a module, it will be assigned a new subsys_id and set
3613 * up for use. If the subsystem is built-in anyway, work is delegated to the 3618 * up for use. If the subsystem is built-in anyway, work is delegated to the
3614 * simpler cgroup_init_subsys. 3619 * simpler cgroup_init_subsys.
3615 */ 3620 */
@@ -4429,7 +4434,15 @@ __setup("cgroup_disable=", cgroup_disable);
4429 */ 4434 */
4430unsigned short css_id(struct cgroup_subsys_state *css) 4435unsigned short css_id(struct cgroup_subsys_state *css)
4431{ 4436{
4432 struct css_id *cssid = rcu_dereference(css->id); 4437 struct css_id *cssid;
4438
4439 /*
4440 * This css_id() can return correct value when somone has refcnt
4441 * on this or this is under rcu_read_lock(). Once css->id is allocated,
4442 * it's unchanged until freed.
4443 */
4444 cssid = rcu_dereference_check(css->id,
4445 rcu_read_lock_held() || atomic_read(&css->refcnt));
4433 4446
4434 if (cssid) 4447 if (cssid)
4435 return cssid->id; 4448 return cssid->id;
@@ -4439,7 +4452,10 @@ EXPORT_SYMBOL_GPL(css_id);
4439 4452
4440unsigned short css_depth(struct cgroup_subsys_state *css) 4453unsigned short css_depth(struct cgroup_subsys_state *css)
4441{ 4454{
4442 struct css_id *cssid = rcu_dereference(css->id); 4455 struct css_id *cssid;
4456
4457 cssid = rcu_dereference_check(css->id,
4458 rcu_read_lock_held() || atomic_read(&css->refcnt));
4443 4459
4444 if (cssid) 4460 if (cssid)
4445 return cssid->depth; 4461 return cssid->depth;
@@ -4447,15 +4463,36 @@ unsigned short css_depth(struct cgroup_subsys_state *css)
4447} 4463}
4448EXPORT_SYMBOL_GPL(css_depth); 4464EXPORT_SYMBOL_GPL(css_depth);
4449 4465
4466/**
4467 * css_is_ancestor - test "root" css is an ancestor of "child"
4468 * @child: the css to be tested.
4469 * @root: the css supporsed to be an ancestor of the child.
4470 *
4471 * Returns true if "root" is an ancestor of "child" in its hierarchy. Because
4472 * this function reads css->id, this use rcu_dereference() and rcu_read_lock().
4473 * But, considering usual usage, the csses should be valid objects after test.
4474 * Assuming that the caller will do some action to the child if this returns
4475 * returns true, the caller must take "child";s reference count.
4476 * If "child" is valid object and this returns true, "root" is valid, too.
4477 */
4478
4450bool css_is_ancestor(struct cgroup_subsys_state *child, 4479bool css_is_ancestor(struct cgroup_subsys_state *child,
4451 const struct cgroup_subsys_state *root) 4480 const struct cgroup_subsys_state *root)
4452{ 4481{
4453 struct css_id *child_id = rcu_dereference(child->id); 4482 struct css_id *child_id;
4454 struct css_id *root_id = rcu_dereference(root->id); 4483 struct css_id *root_id;
4484 bool ret = true;
4455 4485
4456 if (!child_id || !root_id || (child_id->depth < root_id->depth)) 4486 rcu_read_lock();
4457 return false; 4487 child_id = rcu_dereference(child->id);
4458 return child_id->stack[root_id->depth] == root_id->id; 4488 root_id = rcu_dereference(root->id);
4489 if (!child_id
4490 || !root_id
4491 || (child_id->depth < root_id->depth)
4492 || (child_id->stack[root_id->depth] != root_id->id))
4493 ret = false;
4494 rcu_read_unlock();
4495 return ret;
4459} 4496}
4460 4497
4461static void __free_css_id_cb(struct rcu_head *head) 4498static void __free_css_id_cb(struct rcu_head *head)
@@ -4555,13 +4592,13 @@ static int alloc_css_id(struct cgroup_subsys *ss, struct cgroup *parent,
4555{ 4592{
4556 int subsys_id, i, depth = 0; 4593 int subsys_id, i, depth = 0;
4557 struct cgroup_subsys_state *parent_css, *child_css; 4594 struct cgroup_subsys_state *parent_css, *child_css;
4558 struct css_id *child_id, *parent_id = NULL; 4595 struct css_id *child_id, *parent_id;
4559 4596
4560 subsys_id = ss->subsys_id; 4597 subsys_id = ss->subsys_id;
4561 parent_css = parent->subsys[subsys_id]; 4598 parent_css = parent->subsys[subsys_id];
4562 child_css = child->subsys[subsys_id]; 4599 child_css = child->subsys[subsys_id];
4563 depth = css_depth(parent_css) + 1;
4564 parent_id = parent_css->id; 4600 parent_id = parent_css->id;
4601 depth = parent_id->depth + 1;
4565 4602
4566 child_id = get_new_cssid(ss, depth); 4603 child_id = get_new_cssid(ss, depth);
4567 if (IS_ERR(child_id)) 4604 if (IS_ERR(child_id))