aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2011-03-23 19:42:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-23 22:46:23 -0400
commit9d11ea9f163a14920487bdda77461e64d600fd48 (patch)
tree9435e30836ee97f3e8c235451bc944cdc8a345c4 /mm
parentb7c6167848fa36e32f1874b95c1edc02881cd040 (diff)
memcg: simplify the way memory limits are checked
Since transparent huge pages, checking whether memory cgroups are below their limits is no longer enough, but the actual amount of chargeable space is important. To not have more than one limit-checking interface, replace memory_cgroup_check_under_limit() and memory_cgroup_check_margin() with a single memory_cgroup_margin() that returns the chargeable space and leaves the comparison to the callsite. Soft limits are now checked the other way round, by using the already existing function that returns the amount by which soft limits are exceeded: res_counter_soft_limit_excess(). Also remove all the corresponding functions on the res_counter side that are now no longer used. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Minchan Kim <minchan.kim@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/memcontrol.c49
1 files changed, 17 insertions, 32 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 13de53fe0108..62bbb48980e5 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -504,11 +504,6 @@ static void mem_cgroup_remove_from_trees(struct mem_cgroup *mem)
504 } 504 }
505} 505}
506 506
507static inline unsigned long mem_cgroup_get_excess(struct mem_cgroup *mem)
508{
509 return res_counter_soft_limit_excess(&mem->res) >> PAGE_SHIFT;
510}
511
512static struct mem_cgroup_per_zone * 507static struct mem_cgroup_per_zone *
513__mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz) 508__mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
514{ 509{
@@ -1127,33 +1122,21 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
1127#define mem_cgroup_from_res_counter(counter, member) \ 1122#define mem_cgroup_from_res_counter(counter, member) \
1128 container_of(counter, struct mem_cgroup, member) 1123 container_of(counter, struct mem_cgroup, member)
1129 1124
1130static bool mem_cgroup_check_under_limit(struct mem_cgroup *mem)
1131{
1132 if (do_swap_account) {
1133 if (res_counter_check_under_limit(&mem->res) &&
1134 res_counter_check_under_limit(&mem->memsw))
1135 return true;
1136 } else
1137 if (res_counter_check_under_limit(&mem->res))
1138 return true;
1139 return false;
1140}
1141
1142/** 1125/**
1143 * mem_cgroup_check_margin - check if the memory cgroup allows charging 1126 * mem_cgroup_margin - calculate chargeable space of a memory cgroup
1144 * @mem: memory cgroup to check 1127 * @mem: the memory cgroup
1145 * @bytes: the number of bytes the caller intends to charge
1146 * 1128 *
1147 * Returns a boolean value on whether @mem can be charged @bytes or 1129 * Returns the maximum amount of memory @mem can be charged with, in
1148 * whether this would exceed the limit. 1130 * bytes.
1149 */ 1131 */
1150static bool mem_cgroup_check_margin(struct mem_cgroup *mem, unsigned long bytes) 1132static unsigned long long mem_cgroup_margin(struct mem_cgroup *mem)
1151{ 1133{
1152 if (!res_counter_check_margin(&mem->res, bytes)) 1134 unsigned long long margin;
1153 return false; 1135
1154 if (do_swap_account && !res_counter_check_margin(&mem->memsw, bytes)) 1136 margin = res_counter_margin(&mem->res);
1155 return false; 1137 if (do_swap_account)
1156 return true; 1138 margin = min(margin, res_counter_margin(&mem->memsw));
1139 return margin;
1157} 1140}
1158 1141
1159static unsigned int get_swappiness(struct mem_cgroup *memcg) 1142static unsigned int get_swappiness(struct mem_cgroup *memcg)
@@ -1420,7 +1403,9 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
1420 bool noswap = reclaim_options & MEM_CGROUP_RECLAIM_NOSWAP; 1403 bool noswap = reclaim_options & MEM_CGROUP_RECLAIM_NOSWAP;
1421 bool shrink = reclaim_options & MEM_CGROUP_RECLAIM_SHRINK; 1404 bool shrink = reclaim_options & MEM_CGROUP_RECLAIM_SHRINK;
1422 bool check_soft = reclaim_options & MEM_CGROUP_RECLAIM_SOFT; 1405 bool check_soft = reclaim_options & MEM_CGROUP_RECLAIM_SOFT;
1423 unsigned long excess = mem_cgroup_get_excess(root_mem); 1406 unsigned long excess;
1407
1408 excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT;
1424 1409
1425 /* If memsw_is_minimum==1, swap-out is of-no-use. */ 1410 /* If memsw_is_minimum==1, swap-out is of-no-use. */
1426 if (root_mem->memsw_is_minimum) 1411 if (root_mem->memsw_is_minimum)
@@ -1477,9 +1462,9 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
1477 return ret; 1462 return ret;
1478 total += ret; 1463 total += ret;
1479 if (check_soft) { 1464 if (check_soft) {
1480 if (res_counter_check_within_soft_limit(&root_mem->res)) 1465 if (!res_counter_soft_limit_excess(&root_mem->res))
1481 return total; 1466 return total;
1482 } else if (mem_cgroup_check_under_limit(root_mem)) 1467 } else if (mem_cgroup_margin(root_mem))
1483 return 1 + total; 1468 return 1 + total;
1484 } 1469 }
1485 return total; 1470 return total;
@@ -1898,7 +1883,7 @@ static int __mem_cgroup_do_charge(struct mem_cgroup *mem, gfp_t gfp_mask,
1898 1883
1899 ret = mem_cgroup_hierarchical_reclaim(mem_over_limit, NULL, 1884 ret = mem_cgroup_hierarchical_reclaim(mem_over_limit, NULL,
1900 gfp_mask, flags); 1885 gfp_mask, flags);
1901 if (mem_cgroup_check_margin(mem_over_limit, csize)) 1886 if (mem_cgroup_margin(mem_over_limit) >= csize)
1902 return CHARGE_RETRY; 1887 return CHARGE_RETRY;
1903 /* 1888 /*
1904 * Even though the limit is exceeded at this point, reclaim 1889 * Even though the limit is exceeded at this point, reclaim