diff options
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r-- | mm/memcontrol.c | 18 |
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: | |||
1117 | * skipped and we should continue the tree walk. | 1117 | * skipped and we should continue the tree walk. |
1118 | * last_visited css is safe to use because it is | 1118 | * last_visited css is safe to use because it is |
1119 | * protected by css_get and the tree walk is rcu safe. | 1119 | * protected by css_get and the tree walk is rcu safe. |
1120 | * | ||
1121 | * We do not take a reference on the root of the tree walk | ||
1122 | * because we might race with the root removal when it would | ||
1123 | * be the only node in the iterated hierarchy and mem_cgroup_iter | ||
1124 | * would end up in an endless loop because it expects that at | ||
1125 | * least one valid node will be returned. Root cannot disappear | ||
1126 | * because caller of the iterator should hold it already so | ||
1127 | * skipping css reference should be safe. | ||
1120 | */ | 1128 | */ |
1121 | if (next_css) { | 1129 | if (next_css) { |
1122 | if ((next_css->flags & CSS_ONLINE) && css_tryget(next_css)) | 1130 | if ((next_css->flags & CSS_ONLINE) && |
1131 | (next_css == &root->css || css_tryget(next_css))) | ||
1123 | return mem_cgroup_from_css(next_css); | 1132 | return mem_cgroup_from_css(next_css); |
1124 | else { | 1133 | |
1125 | prev_css = next_css; | 1134 | prev_css = next_css; |
1126 | goto skip_node; | 1135 | goto skip_node; |
1127 | } | ||
1128 | } | 1136 | } |
1129 | 1137 | ||
1130 | return NULL; | 1138 | return NULL; |