History

memcg: fix low limit calculation

A memcg is considered low limited even when the current usage is equal to the low limit. This leads to interesting side effects e.g. groups/hierarchies with no memory accounted are considered protected and so the reclaim will emit MEMCG_LOW event when encountering them. Another and much bigger issue was reported by Joonsoo Kim. He has hit a NULL ptr dereference with the legacy cgroup API which even doesn't have low limit exposed. The limit is 0 by default but the initial check fails for memcg with 0 consumption and parent_mem_cgroup() would return NULL if use_hierarchy is 0 and so page_counter_read would try to dereference NULL. I suppose that the current implementation is just an overlook because the documentation in Documentation/cgroups/unified-hierarchy.txt says: "The memory.low boundary on the other hand is a top-down allocated reserve. A cgroup enjoys reclaim protection when it and all its ancestors are below their low boundaries" Fix the usage and the low limit comparision in mem_cgroup_low accordingly.

Michal Hocko committed 11 years ago

Commit 4e54ded1 parent da616531 file · +2 −2Browse files

Unified · Split

mm/memcontrol.c+2−2
@@ -5426,7 +5426,7 @@ bool mem_cgroup_low(struct mem_cgroup *root, struct mem_cgroup *memcg) · 5425 unmodified lines
5426 if (memcg == root_mem_cgroup)5426 if (memcg == root_mem_cgroup)
5427 return false;5427 return false;
5428 5428
5429 if (page_counter_read(&memcg->memory) > memcg->low)5429 if (page_counter_read(&memcg->memory) >= memcg->low)
5430 return false;5430 return false;
5431 5431
5432 while (memcg != root) {5432 while (memcg != root) {
@@ -5435,7 +5435,7 @@ bool mem_cgroup_low(struct mem_cgroup *root, struct mem_cgroup *memcg) · 2 unmodified lines
5435 if (memcg == root_mem_cgroup)5435 if (memcg == root_mem_cgroup)
5436 break;5436 break;
5437 5437
5438 if (page_counter_read(&memcg->memory) > memcg->low)5438 if (page_counter_read(&memcg->memory) >= memcg->low)
5439 return false;5439 return false;
5440 }5440 }
5441 return true;5441 return true;