diff options
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r-- | mm/memcontrol.c | 52 |
1 files changed, 25 insertions, 27 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 408a5c75d77d..614d0d9c0deb 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1116,7 +1116,6 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root, | |||
1116 | rcu_read_lock(); | 1116 | rcu_read_lock(); |
1117 | while (!memcg) { | 1117 | while (!memcg) { |
1118 | struct mem_cgroup_reclaim_iter *uninitialized_var(iter); | 1118 | struct mem_cgroup_reclaim_iter *uninitialized_var(iter); |
1119 | struct cgroup_subsys_state *css = NULL; | ||
1120 | 1119 | ||
1121 | if (reclaim) { | 1120 | if (reclaim) { |
1122 | int nid = zone_to_nid(reclaim->zone); | 1121 | int nid = zone_to_nid(reclaim->zone); |
@@ -1159,51 +1158,50 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root, | |||
1159 | * explicit visit. | 1158 | * explicit visit. |
1160 | */ | 1159 | */ |
1161 | if (!last_visited) { | 1160 | if (!last_visited) { |
1162 | css = &root->css; | 1161 | memcg = root; |
1163 | } else { | 1162 | } else { |
1164 | struct cgroup *prev_cgroup, *next_cgroup; | 1163 | struct cgroup *prev_cgroup, *next_cgroup; |
1165 | 1164 | ||
1166 | prev_cgroup = (last_visited == root) ? NULL | 1165 | prev_cgroup = (last_visited == root) ? NULL |
1167 | : last_visited->css.cgroup; | 1166 | : last_visited->css.cgroup; |
1168 | next_cgroup = cgroup_next_descendant_pre(prev_cgroup, | 1167 | skip_node: |
1169 | root->css.cgroup); | 1168 | next_cgroup = cgroup_next_descendant_pre( |
1170 | if (next_cgroup) | 1169 | prev_cgroup, root->css.cgroup); |
1171 | css = cgroup_subsys_state(next_cgroup, | ||
1172 | mem_cgroup_subsys_id); | ||
1173 | } | ||
1174 | 1170 | ||
1175 | /* | 1171 | /* |
1176 | * Even if we found a group we have to make sure it is alive. | 1172 | * Even if we found a group we have to make sure it is |
1177 | * css && !memcg means that the groups should be skipped and | 1173 | * alive. css && !memcg means that the groups should be |
1178 | * we should continue the tree walk. | 1174 | * skipped and we should continue the tree walk. |
1179 | * last_visited css is safe to use because it is protected by | 1175 | * last_visited css is safe to use because it is |
1180 | * css_get and the tree walk is rcu safe. | 1176 | * protected by css_get and the tree walk is rcu safe. |
1181 | */ | 1177 | */ |
1182 | if (css == &root->css || (css && css_tryget(css))) | 1178 | if (next_cgroup) { |
1183 | memcg = mem_cgroup_from_css(css); | 1179 | struct mem_cgroup *mem = mem_cgroup_from_cont( |
1180 | next_cgroup); | ||
1181 | if (css_tryget(&mem->css)) | ||
1182 | memcg = mem; | ||
1183 | else { | ||
1184 | prev_cgroup = next_cgroup; | ||
1185 | goto skip_node; | ||
1186 | } | ||
1187 | } | ||
1188 | } | ||
1184 | 1189 | ||
1185 | if (reclaim) { | 1190 | if (reclaim) { |
1186 | struct mem_cgroup *curr = memcg; | ||
1187 | |||
1188 | if (last_visited) | 1191 | if (last_visited) |
1189 | css_put(&last_visited->css); | 1192 | css_put(&last_visited->css); |
1190 | 1193 | ||
1191 | if (css && !memcg) | 1194 | iter->last_visited = memcg; |
1192 | curr = mem_cgroup_from_css(css); | ||
1193 | |||
1194 | iter->last_visited = curr; | ||
1195 | smp_wmb(); | 1195 | smp_wmb(); |
1196 | iter->last_dead_count = dead_count; | 1196 | iter->last_dead_count = dead_count; |
1197 | 1197 | ||
1198 | if (!css) | 1198 | if (!memcg) |
1199 | iter->generation++; | 1199 | iter->generation++; |
1200 | else if (!prev && memcg) | 1200 | else if (!prev && memcg) |
1201 | reclaim->generation = iter->generation; | 1201 | reclaim->generation = iter->generation; |
1202 | } else if (css && !memcg) { | ||
1203 | last_visited = mem_cgroup_from_css(css); | ||
1204 | } | 1202 | } |
1205 | 1203 | ||
1206 | if (prev && !css) | 1204 | if (prev && !memcg) |
1207 | goto out_unlock; | 1205 | goto out_unlock; |
1208 | } | 1206 | } |
1209 | out_unlock: | 1207 | out_unlock: |