--- /dev/null
+From ab3f5faa6255a0eb4f832675507d9e295ca7e9ba Mon Sep 17 00:00:00 2001
+From: Hugh Dickins <hughd@google.com>
+Date: Thu, 6 Feb 2014 15:56:01 -0800
+Subject: cgroup: use an ordered workqueue for cgroup destruction
+
+From: Hugh Dickins <hughd@google.com>
+
+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 <filbranden@google.com>
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/cgroup.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -4699,12 +4699,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);
+ BUG_ON(!cgroup_destroy_wq);
+ return 0;
+ }
--- /dev/null
+From ecc736fc3c71c411a9d201d8588c9e7e049e5d8c Mon Sep 17 00:00:00 2001
+From: Michal Hocko <mhocko@suse.cz>
+Date: Thu, 23 Jan 2014 15:53:35 -0800
+Subject: memcg: fix endless loop caused by mem_cgroup_iter
+
+From: Michal Hocko <mhocko@suse.cz>
+
+commit ecc736fc3c71c411a9d201d8588c9e7e049e5d8c upstream.
+
+Hugh has reported an endless loop when the hardlimit reclaim sees the
+same group all the time. This might happen when the reclaim races with
+the memcg removal.
+
+shrink_zone
+ [rmdir root]
+ mem_cgroup_iter(root, NULL, reclaim)
+ // prev = NULL
+ rcu_read_lock()
+ mem_cgroup_iter_load
+ last_visited = iter->last_visited // gets root || NULL
+ css_tryget(last_visited) // failed
+ last_visited = NULL [1]
+ memcg = root = __mem_cgroup_iter_next(root, NULL)
+ mem_cgroup_iter_update
+ iter->last_visited = root;
+ reclaim->generation = iter->generation
+
+ mem_cgroup_iter(root, root, reclaim)
+ // prev = root
+ rcu_read_lock
+ mem_cgroup_iter_load
+ last_visited = iter->last_visited // gets root
+ css_tryget(last_visited) // failed
+ [1]
+
+The issue seemed to be introduced by commit 5f5781619718 ("memcg: relax
+memcg iter caching") which has replaced unconditional css_get/css_put by
+css_tryget/css_put for the cached iterator.
+
+This patch fixes the issue by skipping css_tryget on the root of the
+tree walk in mem_cgroup_iter_load and symmetrically doesn't release it
+in mem_cgroup_iter_update.
+
+Signed-off-by: Michal Hocko <mhocko@suse.cz>
+Reported-by: Hugh Dickins <hughd@google.com>
+Tested-by: Hugh Dickins <hughd@google.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Greg Thelen <gthelen@google.com>
+Cc: <stable@vger.kernel.org> [3.10+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/memcontrol.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -1220,7 +1220,7 @@ struct mem_cgroup *mem_cgroup_iter(struc
+ if (dead_count == iter->last_dead_count) {
+ smp_rmb();
+ last_visited = iter->last_visited;
+- if (last_visited &&
++ if (last_visited && last_visited != root &&
+ !css_tryget(&last_visited->css))
+ last_visited = NULL;
+ }
+@@ -1229,7 +1229,7 @@ struct mem_cgroup *mem_cgroup_iter(struc
+ memcg = __mem_cgroup_iter_next(root, last_visited);
+
+ if (reclaim) {
+- if (last_visited)
++ if (last_visited && last_visited != root)
+ css_put(&last_visited->css);
+
+ iter->last_visited = memcg;