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 | } |
