|
@@ -1073,6 +1073,51 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
|
|
|
return memcg;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Returns a next (in a pre-order walk) alive memcg (with elevated css
|
|
|
+ * ref. count) or NULL if the whole root's subtree has been visited.
|
|
|
+ *
|
|
|
+ * helper function to be used by mem_cgroup_iter
|
|
|
+ */
|
|
|
+static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root,
|
|
|
+ struct mem_cgroup *last_visited)
|
|
|
+{
|
|
|
+ struct cgroup *prev_cgroup, *next_cgroup;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Root is not visited by cgroup iterators so it needs an
|
|
|
+ * explicit visit.
|
|
|
+ */
|
|
|
+ if (!last_visited)
|
|
|
+ return root;
|
|
|
+
|
|
|
+ prev_cgroup = (last_visited == root) ? NULL
|
|
|
+ : last_visited->css.cgroup;
|
|
|
+skip_node:
|
|
|
+ next_cgroup = cgroup_next_descendant_pre(
|
|
|
+ prev_cgroup, root->css.cgroup);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Even if we found a group we have to make sure it is
|
|
|
+ * alive. css && !memcg means that the groups should be
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+ if (next_cgroup) {
|
|
|
+ struct mem_cgroup *mem = mem_cgroup_from_cont(
|
|
|
+ next_cgroup);
|
|
|
+ if (css_tryget(&mem->css))
|
|
|
+ return mem;
|
|
|
+ else {
|
|
|
+ prev_cgroup = next_cgroup;
|
|
|
+ goto skip_node;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* mem_cgroup_iter - iterate over memory cgroup hierarchy
|
|
|
* @root: hierarchy root
|
|
@@ -1153,39 +1198,7 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Root is not visited by cgroup iterators so it needs an
|
|
|
- * explicit visit.
|
|
|
- */
|
|
|
- if (!last_visited) {
|
|
|
- memcg = root;
|
|
|
- } else {
|
|
|
- struct cgroup *prev_cgroup, *next_cgroup;
|
|
|
-
|
|
|
- prev_cgroup = (last_visited == root) ? NULL
|
|
|
- : last_visited->css.cgroup;
|
|
|
-skip_node:
|
|
|
- next_cgroup = cgroup_next_descendant_pre(
|
|
|
- prev_cgroup, root->css.cgroup);
|
|
|
-
|
|
|
- /*
|
|
|
- * Even if we found a group we have to make sure it is
|
|
|
- * alive. css && !memcg means that the groups should be
|
|
|
- * 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.
|
|
|
- */
|
|
|
- if (next_cgroup) {
|
|
|
- struct mem_cgroup *mem = mem_cgroup_from_cont(
|
|
|
- next_cgroup);
|
|
|
- if (css_tryget(&mem->css))
|
|
|
- memcg = mem;
|
|
|
- else {
|
|
|
- prev_cgroup = next_cgroup;
|
|
|
- goto skip_node;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ memcg = __mem_cgroup_iter_next(root, last_visited);
|
|
|
|
|
|
if (reclaim) {
|
|
|
if (last_visited)
|