diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2008-11-19 18:36:34 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-19 21:49:58 -0500 |
commit | 3fa59dfbc3b223f02c26593be69ce6fc9a940405 (patch) | |
tree | d3d9df521342b49abc636e1ee465b704858b3e0d /kernel | |
parent | 0ae15132a4f5c758a6ffcde74495641dc3f62ba1 (diff) |
cgroup: fix potential deadlock in pre_destroy
As Balbir pointed out, memcg's pre_destroy handler has potential deadlock.
It has following lock sequence.
cgroup_mutex (cgroup_rmdir)
-> pre_destroy -> mem_cgroup_pre_destroy-> force_empty
-> cpu_hotplug.lock. (lru_add_drain_all->
schedule_work->
get_online_cpus)
But, cpuset has following.
cpu_hotplug.lock (call notifier)
-> cgroup_mutex. (within notifier)
Then, this lock sequence should be fixed.
Considering how pre_destroy works, it's not necessary to holding
cgroup_mutex() while calling it.
As a side effect, we don't have to wait at this mutex while memcg's
force_empty works.(it can be long when there are tons of pages.)
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Paul Menage <menage@google.com>
Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cgroup.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 358e77564e6f..1a06be61dcd0 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2472,10 +2472,7 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
2472 | mutex_unlock(&cgroup_mutex); | 2472 | mutex_unlock(&cgroup_mutex); |
2473 | return -EBUSY; | 2473 | return -EBUSY; |
2474 | } | 2474 | } |
2475 | 2475 | mutex_unlock(&cgroup_mutex); | |
2476 | parent = cgrp->parent; | ||
2477 | root = cgrp->root; | ||
2478 | sb = root->sb; | ||
2479 | 2476 | ||
2480 | /* | 2477 | /* |
2481 | * Call pre_destroy handlers of subsys. Notify subsystems | 2478 | * Call pre_destroy handlers of subsys. Notify subsystems |
@@ -2483,7 +2480,14 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
2483 | */ | 2480 | */ |
2484 | cgroup_call_pre_destroy(cgrp); | 2481 | cgroup_call_pre_destroy(cgrp); |
2485 | 2482 | ||
2486 | if (cgroup_has_css_refs(cgrp)) { | 2483 | mutex_lock(&cgroup_mutex); |
2484 | parent = cgrp->parent; | ||
2485 | root = cgrp->root; | ||
2486 | sb = root->sb; | ||
2487 | |||
2488 | if (atomic_read(&cgrp->count) | ||
2489 | || !list_empty(&cgrp->children) | ||
2490 | || cgroup_has_css_refs(cgrp)) { | ||
2487 | mutex_unlock(&cgroup_mutex); | 2491 | mutex_unlock(&cgroup_mutex); |
2488 | return -EBUSY; | 2492 | return -EBUSY; |
2489 | } | 2493 | } |