diff options
-rw-r--r-- | mm/memcontrol.c | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 614d0d9c0deb..2bdac3ececd0 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1073,6 +1073,51 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) | |||
1073 | return memcg; | 1073 | return memcg; |
1074 | } | 1074 | } |
1075 | 1075 | ||
1076 | /* | ||
1077 | * Returns a next (in a pre-order walk) alive memcg (with elevated css | ||
1078 | * ref. count) or NULL if the whole root's subtree has been visited. | ||
1079 | * | ||
1080 | * helper function to be used by mem_cgroup_iter | ||
1081 | */ | ||
1082 | static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root, | ||
1083 | struct mem_cgroup *last_visited) | ||
1084 | { | ||
1085 | struct cgroup *prev_cgroup, *next_cgroup; | ||
1086 | |||
1087 | /* | ||
1088 | * Root is not visited by cgroup iterators so it needs an | ||
1089 | * explicit visit. | ||
1090 | */ | ||
1091 | if (!last_visited) | ||
1092 | return root; | ||
1093 | |||
1094 | prev_cgroup = (last_visited == root) ? NULL | ||
1095 | : last_visited->css.cgroup; | ||
1096 | skip_node: | ||
1097 | next_cgroup = cgroup_next_descendant_pre( | ||
1098 | prev_cgroup, root->css.cgroup); | ||
1099 | |||
1100 | /* | ||
1101 | * Even if we found a group we have to make sure it is | ||
1102 | * alive. css && !memcg means that the groups should be | ||
1103 | * skipped and we should continue the tree walk. | ||
1104 | * last_visited css is safe to use because it is | ||
1105 | * protected by css_get and the tree walk is rcu safe. | ||
1106 | */ | ||
1107 | if (next_cgroup) { | ||
1108 | struct mem_cgroup *mem = mem_cgroup_from_cont( | ||
1109 | next_cgroup); | ||
1110 | if (css_tryget(&mem->css)) | ||
1111 | return mem; | ||
1112 | else { | ||
1113 | prev_cgroup = next_cgroup; | ||
1114 | goto skip_node; | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | return NULL; | ||
1119 | } | ||
1120 | |||
1076 | /** | 1121 | /** |
1077 | * mem_cgroup_iter - iterate over memory cgroup hierarchy | 1122 | * mem_cgroup_iter - iterate over memory cgroup hierarchy |
1078 | * @root: hierarchy root | 1123 | * @root: hierarchy root |
@@ -1153,39 +1198,7 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root, | |||
1153 | } | 1198 | } |
1154 | } | 1199 | } |
1155 | 1200 | ||
1156 | /* | 1201 | memcg = __mem_cgroup_iter_next(root, last_visited); |
1157 | * Root is not visited by cgroup iterators so it needs an | ||
1158 | * explicit visit. | ||
1159 | */ | ||
1160 | if (!last_visited) { | ||
1161 | memcg = root; | ||
1162 | } else { | ||
1163 | struct cgroup *prev_cgroup, *next_cgroup; | ||
1164 | |||
1165 | prev_cgroup = (last_visited == root) ? NULL | ||
1166 | : last_visited->css.cgroup; | ||
1167 | skip_node: | ||
1168 | next_cgroup = cgroup_next_descendant_pre( | ||
1169 | prev_cgroup, root->css.cgroup); | ||
1170 | |||
1171 | /* | ||
1172 | * Even if we found a group we have to make sure it is | ||
1173 | * alive. css && !memcg means that the groups should be | ||
1174 | * skipped and we should continue the tree walk. | ||
1175 | * last_visited css is safe to use because it is | ||
1176 | * protected by css_get and the tree walk is rcu safe. | ||
1177 | */ | ||
1178 | if (next_cgroup) { | ||
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 | } | ||
1189 | 1202 | ||
1190 | if (reclaim) { | 1203 | if (reclaim) { |
1191 | if (last_visited) | 1204 | if (last_visited) |