diff options
-rw-r--r-- | include/linux/res_counter.h | 72 | ||||
-rw-r--r-- | mm/memcontrol.c | 49 |
2 files changed, 31 insertions, 90 deletions
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h index bf1f01bc013f..c9d625ca659e 100644 --- a/include/linux/res_counter.h +++ b/include/linux/res_counter.h | |||
@@ -129,20 +129,22 @@ int __must_check res_counter_charge(struct res_counter *counter, | |||
129 | void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val); | 129 | void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val); |
130 | void res_counter_uncharge(struct res_counter *counter, unsigned long val); | 130 | void res_counter_uncharge(struct res_counter *counter, unsigned long val); |
131 | 131 | ||
132 | static inline bool res_counter_limit_check_locked(struct res_counter *cnt) | 132 | /** |
133 | { | 133 | * res_counter_margin - calculate chargeable space of a counter |
134 | if (cnt->usage < cnt->limit) | 134 | * @cnt: the counter |
135 | return true; | 135 | * |
136 | 136 | * Returns the difference between the hard limit and the current usage | |
137 | return false; | 137 | * of resource counter @cnt. |
138 | } | 138 | */ |
139 | 139 | static inline unsigned long long res_counter_margin(struct res_counter *cnt) | |
140 | static inline bool res_counter_soft_limit_check_locked(struct res_counter *cnt) | ||
141 | { | 140 | { |
142 | if (cnt->usage <= cnt->soft_limit) | 141 | unsigned long long margin; |
143 | return true; | 142 | unsigned long flags; |
144 | 143 | ||
145 | return false; | 144 | spin_lock_irqsave(&cnt->lock, flags); |
145 | margin = cnt->limit - cnt->usage; | ||
146 | spin_unlock_irqrestore(&cnt->lock, flags); | ||
147 | return margin; | ||
146 | } | 148 | } |
147 | 149 | ||
148 | /** | 150 | /** |
@@ -167,52 +169,6 @@ res_counter_soft_limit_excess(struct res_counter *cnt) | |||
167 | return excess; | 169 | return excess; |
168 | } | 170 | } |
169 | 171 | ||
170 | /* | ||
171 | * Helper function to detect if the cgroup is within it's limit or | ||
172 | * not. It's currently called from cgroup_rss_prepare() | ||
173 | */ | ||
174 | static inline bool res_counter_check_under_limit(struct res_counter *cnt) | ||
175 | { | ||
176 | bool ret; | ||
177 | unsigned long flags; | ||
178 | |||
179 | spin_lock_irqsave(&cnt->lock, flags); | ||
180 | ret = res_counter_limit_check_locked(cnt); | ||
181 | spin_unlock_irqrestore(&cnt->lock, flags); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * res_counter_check_margin - check if the counter allows charging | ||
187 | * @cnt: the resource counter to check | ||
188 | * @bytes: the number of bytes to check the remaining space against | ||
189 | * | ||
190 | * Returns a boolean value on whether the counter can be charged | ||
191 | * @bytes or whether this would exceed the limit. | ||
192 | */ | ||
193 | static inline bool res_counter_check_margin(struct res_counter *cnt, | ||
194 | unsigned long bytes) | ||
195 | { | ||
196 | bool ret; | ||
197 | unsigned long flags; | ||
198 | |||
199 | spin_lock_irqsave(&cnt->lock, flags); | ||
200 | ret = cnt->limit - cnt->usage >= bytes; | ||
201 | spin_unlock_irqrestore(&cnt->lock, flags); | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | static inline bool res_counter_check_within_soft_limit(struct res_counter *cnt) | ||
206 | { | ||
207 | bool ret; | ||
208 | unsigned long flags; | ||
209 | |||
210 | spin_lock_irqsave(&cnt->lock, flags); | ||
211 | ret = res_counter_soft_limit_check_locked(cnt); | ||
212 | spin_unlock_irqrestore(&cnt->lock, flags); | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static inline void res_counter_reset_max(struct res_counter *cnt) | 172 | static inline void res_counter_reset_max(struct res_counter *cnt) |
217 | { | 173 | { |
218 | unsigned long flags; | 174 | unsigned long flags; |
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 | ||
507 | static 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 | |||
512 | static struct mem_cgroup_per_zone * | 507 | static 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 | ||
1130 | static 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 | */ |
1150 | static bool mem_cgroup_check_margin(struct mem_cgroup *mem, unsigned long bytes) | 1132 | static 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 | ||
1159 | static unsigned int get_swappiness(struct mem_cgroup *memcg) | 1142 | static 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 |