summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/memcontrol.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index da07784dde87..98f80beeac7f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1117,14 +1117,22 @@ skip_node:
* skipped and we should continue the tree walk.
* last_visited css is safe to use because it is
* protected by css_get and the tree walk is rcu safe.
+ *
+ * We do not take a reference on the root of the tree walk
+ * because we might race with the root removal when it would
+ * be the only node in the iterated hierarchy and mem_cgroup_iter
+ * would end up in an endless loop because it expects that at
+ * least one valid node will be returned. Root cannot disappear
+ * because caller of the iterator should hold it already so
+ * skipping css reference should be safe.
*/
if (next_css) {
- if ((next_css->flags & CSS_ONLINE) && css_tryget(next_css))
+ if ((next_css->flags & CSS_ONLINE) &&
+ (next_css == &root->css || css_tryget(next_css)))
return mem_cgroup_from_css(next_css);
- else {
- prev_css = next_css;
- goto skip_node;
- }
+
+ prev_css = next_css;
+ goto skip_node;
}
return NULL;