|
@@ -5317,38 +5317,52 @@ struct cgroup_subsys memory_cgrp_subsys = {
|
|
|
|
|
|
/**
|
|
|
* mem_cgroup_low - check if memory consumption is below the normal range
|
|
|
- * @root: the highest ancestor to consider
|
|
|
+ * @root: the top ancestor of the sub-tree being checked
|
|
|
* @memcg: the memory cgroup to check
|
|
|
*
|
|
|
* Returns %true if memory consumption of @memcg, and that of all
|
|
|
- * configurable ancestors up to @root, is below the normal range.
|
|
|
+ * ancestors up to (but not including) @root, is below the normal range.
|
|
|
+ *
|
|
|
+ * @root is exclusive; it is never low when looked at directly and isn't
|
|
|
+ * checked when traversing the hierarchy.
|
|
|
+ *
|
|
|
+ * Excluding @root enables using memory.low to prioritize memory usage
|
|
|
+ * between cgroups within a subtree of the hierarchy that is limited by
|
|
|
+ * memory.high or memory.max.
|
|
|
+ *
|
|
|
+ * For example, given cgroup A with children B and C:
|
|
|
+ *
|
|
|
+ * A
|
|
|
+ * / \
|
|
|
+ * B C
|
|
|
+ *
|
|
|
+ * and
|
|
|
+ *
|
|
|
+ * 1. A/memory.current > A/memory.high
|
|
|
+ * 2. A/B/memory.current < A/B/memory.low
|
|
|
+ * 3. A/C/memory.current >= A/C/memory.low
|
|
|
+ *
|
|
|
+ * As 'A' is high, i.e. triggers reclaim from 'A', and 'B' is low, we
|
|
|
+ * should reclaim from 'C' until 'A' is no longer high or until we can
|
|
|
+ * no longer reclaim from 'C'. If 'A', i.e. @root, isn't excluded by
|
|
|
+ * mem_cgroup_low when reclaming from 'A', then 'B' won't be considered
|
|
|
+ * low and we will reclaim indiscriminately from both 'B' and 'C'.
|
|
|
*/
|
|
|
bool mem_cgroup_low(struct mem_cgroup *root, struct mem_cgroup *memcg)
|
|
|
{
|
|
|
if (mem_cgroup_disabled())
|
|
|
return false;
|
|
|
|
|
|
- /*
|
|
|
- * The toplevel group doesn't have a configurable range, so
|
|
|
- * it's never low when looked at directly, and it is not
|
|
|
- * considered an ancestor when assessing the hierarchy.
|
|
|
- */
|
|
|
-
|
|
|
- if (memcg == root_mem_cgroup)
|
|
|
- return false;
|
|
|
-
|
|
|
- if (page_counter_read(&memcg->memory) >= memcg->low)
|
|
|
+ if (!root)
|
|
|
+ root = root_mem_cgroup;
|
|
|
+ if (memcg == root)
|
|
|
return false;
|
|
|
|
|
|
- while (memcg != root) {
|
|
|
- memcg = parent_mem_cgroup(memcg);
|
|
|
-
|
|
|
- if (memcg == root_mem_cgroup)
|
|
|
- break;
|
|
|
-
|
|
|
+ for (; memcg != root; memcg = parent_mem_cgroup(memcg)) {
|
|
|
if (page_counter_read(&memcg->memory) >= memcg->low)
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|