aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-02-12 09:29:50 -0500
committerTejun Heo <tj@kernel.org>2014-02-12 09:29:50 -0500
commit6f30558f37bfbd428e3854c2c34b5c32117c8f7e (patch)
treec02c711bf750ea306cc008a787335fedfba7feab /kernel/cgroup.c
parent21a2d3430ba8c188af405a5c2eb9c06bdcb6add6 (diff)
cgroup: make cgroup hold onto its kernfs_node
cgroup currently releases its kernfs_node when it gets removed. While not buggy, this makes cgroup->kn access rules complicated than necessary and leads to things like get/put protection around kernfs_remove() in cgroup_destroy_locked(). In addition, we want to use kernfs_name/path() and friends but also want to be able to determine a cgroup's name between removal and release. This patch makes cgroup hold onto its kernfs_node until freed so that cgroup->kn is always accessible. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index f4409715a2f5..59dfb025f1ac 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -957,6 +957,8 @@ static void cgroup_free_fn(struct work_struct *work)
957 957
958 cgroup_pidlist_destroy_all(cgrp); 958 cgroup_pidlist_destroy_all(cgrp);
959 959
960 kernfs_put(cgrp->kn);
961
960 kfree(rcu_dereference_raw(cgrp->name)); 962 kfree(rcu_dereference_raw(cgrp->name));
961 kfree(cgrp); 963 kfree(cgrp);
962} 964}
@@ -3786,6 +3788,12 @@ static long cgroup_create(struct cgroup *parent, const char *name_str,
3786 } 3788 }
3787 cgrp->kn = kn; 3789 cgrp->kn = kn;
3788 3790
3791 /*
3792 * This extra ref will be put in cgroup_free_fn() and guarantees
3793 * that @cgrp->kn is always accessible.
3794 */
3795 kernfs_get(kn);
3796
3789 cgrp->serial_nr = cgroup_serial_nr_next++; 3797 cgrp->serial_nr = cgroup_serial_nr_next++;
3790 3798
3791 /* allocation complete, commit to creation */ 3799 /* allocation complete, commit to creation */
@@ -3966,7 +3974,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
3966{ 3974{
3967 struct cgroup *child; 3975 struct cgroup *child;
3968 struct cgroup_subsys_state *css; 3976 struct cgroup_subsys_state *css;
3969 struct kernfs_node *kn;
3970 bool empty; 3977 bool empty;
3971 int ssid; 3978 int ssid;
3972 3979
@@ -4044,13 +4051,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4044 * clearing of cgrp->kn->priv backpointer, which should happen 4051 * clearing of cgrp->kn->priv backpointer, which should happen
4045 * after all files under it have been removed. 4052 * after all files under it have been removed.
4046 */ 4053 */
4047 kn = cgrp->kn; 4054 kernfs_remove(cgrp->kn); /* @cgrp has an extra ref on its kn */
4048 kernfs_get(kn);
4049
4050 kernfs_remove(cgrp->kn);
4051
4052 RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv, NULL); 4055 RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv, NULL);
4053 kernfs_put(kn);
4054 4056
4055 mutex_lock(&cgroup_mutex); 4057 mutex_lock(&cgroup_mutex);
4056 4058