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 | |
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>
-rw-r--r-- | kernel/cgroup.c | 15 | ||||
-rw-r--r-- | mm/memcontrol.c | 19 |
2 files changed, 18 insertions, 16 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; |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0f711c213d2e..595d03f33b2c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -2314,9 +2314,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) | |||
2314 | 2314 | ||
2315 | /* record memcg information */ | 2315 | /* record memcg information */ |
2316 | if (do_swap_account && swapout && memcg) { | 2316 | if (do_swap_account && swapout && memcg) { |
2317 | rcu_read_lock(); | ||
2318 | swap_cgroup_record(ent, css_id(&memcg->css)); | 2317 | swap_cgroup_record(ent, css_id(&memcg->css)); |
2319 | rcu_read_unlock(); | ||
2320 | mem_cgroup_get(memcg); | 2318 | mem_cgroup_get(memcg); |
2321 | } | 2319 | } |
2322 | if (swapout && memcg) | 2320 | if (swapout && memcg) |
@@ -2373,10 +2371,8 @@ static int mem_cgroup_move_swap_account(swp_entry_t entry, | |||
2373 | { | 2371 | { |
2374 | unsigned short old_id, new_id; | 2372 | unsigned short old_id, new_id; |
2375 | 2373 | ||
2376 | rcu_read_lock(); | ||
2377 | old_id = css_id(&from->css); | 2374 | old_id = css_id(&from->css); |
2378 | new_id = css_id(&to->css); | 2375 | new_id = css_id(&to->css); |
2379 | rcu_read_unlock(); | ||
2380 | 2376 | ||
2381 | if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) { | 2377 | if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) { |
2382 | mem_cgroup_swap_statistics(from, false); | 2378 | mem_cgroup_swap_statistics(from, false); |
@@ -4044,16 +4040,11 @@ static int is_target_pte_for_mc(struct vm_area_struct *vma, | |||
4044 | put_page(page); | 4040 | put_page(page); |
4045 | } | 4041 | } |
4046 | /* throught */ | 4042 | /* throught */ |
4047 | if (ent.val && do_swap_account && !ret) { | 4043 | if (ent.val && do_swap_account && !ret && |
4048 | unsigned short id; | 4044 | css_id(&mc.from->css) == lookup_swap_cgroup(ent)) { |
4049 | rcu_read_lock(); | 4045 | ret = MC_TARGET_SWAP; |
4050 | id = css_id(&mc.from->css); | 4046 | if (target) |
4051 | rcu_read_unlock(); | 4047 | target->ent = ent; |
4052 | if (id == lookup_swap_cgroup(ent)) { | ||
4053 | ret = MC_TARGET_SWAP; | ||
4054 | if (target) | ||
4055 | target->ent = ent; | ||
4056 | } | ||
4057 | } | 4048 | } |
4058 | return ret; | 4049 | return ret; |
4059 | } | 4050 | } |