diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2010-05-11 17:06:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-11 20:33:42 -0400 |
commit | 7f0f15464185a92f9d8791ad231bcd7bf6df54e4 (patch) | |
tree | a1d4f4c39632659497963b0ccf62828237478d72 /kernel/cgroup.c | |
parent | 11cad320a4f4bc53d3585c85600c782faa12b99e (diff) |
memcg: fix css_id() RCU locking for real
Commit ad4ba375373937817404fd92239ef4cadbded23b ("memcg: css_id() must be
called under rcu_read_lock()") modifies memcontol.c for fixing RCU check
message. But Andrew Morton pointed out that the fix doesn't seems sane
and it was just for hidining lockdep messages.
This is a patch for do proper things. Checking again, all places,
accessing without rcu_read_lock, that commit fixies was intentional....
all callers of css_id() has reference count on it. So, it's not necessary
to be under rcu_read_lock().
Considering again, we can use rcu_dereference_check for css_id(). We know
css->id is valid if css->refcnt > 0. (css->id never changes and freed
after css->refcnt going to be 0.)
This patch makes use of rcu_dereference_check() in css_id/depth and remove
unnecessary rcu-read-lock added by the commit.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Cc: Balbir Singh <balbir@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 3a53c771e503..6db8b7f297a1 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4435,7 +4435,15 @@ __setup("cgroup_disable=", cgroup_disable); | |||
4435 | */ | 4435 | */ |
4436 | unsigned short css_id(struct cgroup_subsys_state *css) | 4436 | unsigned short css_id(struct cgroup_subsys_state *css) |
4437 | { | 4437 | { |
4438 | struct css_id *cssid = rcu_dereference(css->id); | 4438 | struct css_id *cssid; |
4439 | |||
4440 | /* | ||
4441 | * This css_id() can return correct value when somone has refcnt | ||
4442 | * on this or this is under rcu_read_lock(). Once css->id is allocated, | ||
4443 | * it's unchanged until freed. | ||
4444 | */ | ||
4445 | cssid = rcu_dereference_check(css->id, | ||
4446 | rcu_read_lock_held() || atomic_read(&css->refcnt)); | ||
4439 | 4447 | ||
4440 | if (cssid) | 4448 | if (cssid) |
4441 | return cssid->id; | 4449 | return cssid->id; |
@@ -4445,7 +4453,10 @@ EXPORT_SYMBOL_GPL(css_id); | |||
4445 | 4453 | ||
4446 | unsigned short css_depth(struct cgroup_subsys_state *css) | 4454 | unsigned short css_depth(struct cgroup_subsys_state *css) |
4447 | { | 4455 | { |
4448 | struct css_id *cssid = rcu_dereference(css->id); | 4456 | struct css_id *cssid; |
4457 | |||
4458 | cssid = rcu_dereference_check(css->id, | ||
4459 | rcu_read_lock_held() || atomic_read(&css->refcnt)); | ||
4449 | 4460 | ||
4450 | if (cssid) | 4461 | if (cssid) |
4451 | return cssid->depth; | 4462 | return cssid->depth; |