diff options
author | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:36 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:36 -0500 |
commit | febfcef60d4f9457785b45aab548bc7ee5ea158f (patch) | |
tree | 70fab0e8ec07aec4142f1dc228f307e6b1d79de0 /kernel/cgroup.c | |
parent | 4e139afc22cb98d0d032ffce0285bfcc73ca5217 (diff) |
cgroup: cgroup->dentry isn't a RCU pointer
cgroup->dentry is marked and used as a RCU pointer; however, it isn't
one - the final dentry put doesn't go through call_rcu(). cgroup and
dentry share the same RCU freeing rule via synchronize_rcu() in
cgroup_diput() (kfree_rcu() used on cgrp is unnecessary). If cgrp is
accessible under RCU read lock, so is its dentry and dereferencing
cgrp->dentry doesn't need any further RCU protection or annotation.
While not being accurate, before the previous patch, the RCU accessors
served a purpose as memory barriers - cgroup->dentry used to be
assigned after the cgroup was made visible to cgroup_path(), so the
assignment and dereferencing in cgroup_path() needed the memory
barrier pair. Now that list_add_tail_rcu() happens after
cgroup->dentry is assigned, this no longer is necessary.
Remove the now unnecessary and misleading RCU annotations from
cgroup->dentry. To make up for the removal of rcu_dereference_check()
in cgroup_path(), add an explicit rcu_lockdep_assert(), which asserts
the dereference rule of @cgrp, not cgrp->dentry.
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.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index d62a529db2f7..affc76d7f739 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1756,9 +1756,11 @@ static struct kobject *cgroup_kobj; | |||
1756 | */ | 1756 | */ |
1757 | int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) | 1757 | int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) |
1758 | { | 1758 | { |
1759 | struct dentry *dentry = cgrp->dentry; | ||
1759 | char *start; | 1760 | char *start; |
1760 | struct dentry *dentry = rcu_dereference_check(cgrp->dentry, | 1761 | |
1761 | cgroup_lock_is_held()); | 1762 | rcu_lockdep_assert(rcu_read_lock_held() || cgroup_lock_is_held(), |
1763 | "cgroup_path() called without proper locking"); | ||
1762 | 1764 | ||
1763 | if (!dentry || cgrp == dummytop) { | 1765 | if (!dentry || cgrp == dummytop) { |
1764 | /* | 1766 | /* |
@@ -1782,8 +1784,7 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) | |||
1782 | if (!cgrp) | 1784 | if (!cgrp) |
1783 | break; | 1785 | break; |
1784 | 1786 | ||
1785 | dentry = rcu_dereference_check(cgrp->dentry, | 1787 | dentry = cgrp->dentry; |
1786 | cgroup_lock_is_held()); | ||
1787 | if (!cgrp->parent) | 1788 | if (!cgrp->parent) |
1788 | continue; | 1789 | continue; |
1789 | if (--start < buf) | 1790 | if (--start < buf) |
@@ -4124,7 +4125,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
4124 | 4125 | ||
4125 | /* allocation complete, commit to creation */ | 4126 | /* allocation complete, commit to creation */ |
4126 | dentry->d_fsdata = cgrp; | 4127 | dentry->d_fsdata = cgrp; |
4127 | rcu_assign_pointer(cgrp->dentry, dentry); | 4128 | cgrp->dentry = dentry; |
4128 | list_add_tail(&cgrp->allcg_node, &root->allcg_list); | 4129 | list_add_tail(&cgrp->allcg_node, &root->allcg_list); |
4129 | list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children); | 4130 | list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children); |
4130 | root->number_of_cgroups++; | 4131 | root->number_of_cgroups++; |