[lkml]   [2017]   [Apr]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
Patch in this message
Subject[PATCH 3.12 127/142] cgroup: use an ordered workqueue for cgroup destruction
From: Hugh Dickins <>

3.12-stable review patch. If anyone has any objections, please let me know.


commit ab3f5faa6255a0eb4f832675507d9e295ca7e9ba upstream.

Sometimes the cleanup after memcg hierarchy testing gets stuck in
mem_cgroup_reparent_charges(), unable to bring non-kmem usage down to 0.

There may turn out to be several causes, but a major cause is this: the
workitem to offline parent can get run before workitem to offline child;
parent's mem_cgroup_reparent_charges() circles around waiting for the
child's pages to be reparented to its lrus, but it's holding cgroup_mutex
which prevents the child from reaching its mem_cgroup_reparent_charges().

Just use an ordered workqueue for cgroup_destroy_wq.

tj: Committing as the temporary fix until the reverse dependency can
be removed from memcg. Comment updated accordingly.

Fixes: e5fca243abae ("cgroup: use a dedicated workqueue for cgroup destruction")
Suggested-by: Filipe Brandenburger <>
Signed-off-by: Hugh Dickins <>
Signed-off-by: Tejun Heo <>
Signed-off-by: Jiri Slaby <>
kernel/cgroup.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 5d9d542c0bb5..e89f6cec01c9 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -5168,12 +5168,16 @@ static int __init cgroup_wq_init(void)
* There isn't much point in executing destruction path in
* parallel. Good chunk is serialized with cgroup_mutex anyway.
- * Use 1 for @max_active.
+ *
+ * XXX: Must be ordered to make sure parent is offlined after
+ * children. The ordering requirement is for memcg where a
+ * parent's offline may wait for a child's leading to deadlock. In
+ * the long term, this should be fixed from memcg side.
* We would prefer to do this in cgroup_init() above, but that
* is called before init_workqueues(): so leave this until after.
- cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1);
+ cgroup_destroy_wq = alloc_ordered_workqueue("cgroup_destroy", 0);
return 0;
 \ /
  Last update: 2017-04-10 17:39    [W:0.366 / U:11.852 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site