diff options
-rw-r--r-- | include/linux/res_counter.h | 20 | ||||
-rw-r--r-- | mm/memcontrol.c | 35 |
2 files changed, 48 insertions, 7 deletions
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h index fcb9884df618..a5930cb66145 100644 --- a/include/linux/res_counter.h +++ b/include/linux/res_counter.h | |||
@@ -182,6 +182,26 @@ static inline bool res_counter_check_under_limit(struct res_counter *cnt) | |||
182 | return ret; | 182 | return ret; |
183 | } | 183 | } |
184 | 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 | |||
185 | static inline bool res_counter_check_under_soft_limit(struct res_counter *cnt) | 205 | static inline bool res_counter_check_under_soft_limit(struct res_counter *cnt) |
186 | { | 206 | { |
187 | bool ret; | 207 | bool ret; |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 50eb50e100fd..0e81eb5f0aea 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1111,6 +1111,23 @@ static bool mem_cgroup_check_under_limit(struct mem_cgroup *mem) | |||
1111 | return false; | 1111 | return false; |
1112 | } | 1112 | } |
1113 | 1113 | ||
1114 | /** | ||
1115 | * mem_cgroup_check_margin - check if the memory cgroup allows charging | ||
1116 | * @mem: memory cgroup to check | ||
1117 | * @bytes: the number of bytes the caller intends to charge | ||
1118 | * | ||
1119 | * Returns a boolean value on whether @mem can be charged @bytes or | ||
1120 | * whether this would exceed the limit. | ||
1121 | */ | ||
1122 | static bool mem_cgroup_check_margin(struct mem_cgroup *mem, unsigned long bytes) | ||
1123 | { | ||
1124 | if (!res_counter_check_margin(&mem->res, bytes)) | ||
1125 | return false; | ||
1126 | if (do_swap_account && !res_counter_check_margin(&mem->memsw, bytes)) | ||
1127 | return false; | ||
1128 | return true; | ||
1129 | } | ||
1130 | |||
1114 | static unsigned int get_swappiness(struct mem_cgroup *memcg) | 1131 | static unsigned int get_swappiness(struct mem_cgroup *memcg) |
1115 | { | 1132 | { |
1116 | struct cgroup *cgrp = memcg->css.cgroup; | 1133 | struct cgroup *cgrp = memcg->css.cgroup; |
@@ -1852,15 +1869,19 @@ static int __mem_cgroup_do_charge(struct mem_cgroup *mem, gfp_t gfp_mask, | |||
1852 | return CHARGE_WOULDBLOCK; | 1869 | return CHARGE_WOULDBLOCK; |
1853 | 1870 | ||
1854 | ret = mem_cgroup_hierarchical_reclaim(mem_over_limit, NULL, | 1871 | ret = mem_cgroup_hierarchical_reclaim(mem_over_limit, NULL, |
1855 | gfp_mask, flags); | 1872 | gfp_mask, flags); |
1873 | if (mem_cgroup_check_margin(mem_over_limit, csize)) | ||
1874 | return CHARGE_RETRY; | ||
1856 | /* | 1875 | /* |
1857 | * try_to_free_mem_cgroup_pages() might not give us a full | 1876 | * Even though the limit is exceeded at this point, reclaim |
1858 | * picture of reclaim. Some pages are reclaimed and might be | 1877 | * may have been able to free some pages. Retry the charge |
1859 | * moved to swap cache or just unmapped from the cgroup. | 1878 | * before killing the task. |
1860 | * Check the limit again to see if the reclaim reduced the | 1879 | * |
1861 | * current usage of the cgroup before giving up | 1880 | * Only for regular pages, though: huge pages are rather |
1881 | * unlikely to succeed so close to the limit, and we fall back | ||
1882 | * to regular pages anyway in case of failure. | ||
1862 | */ | 1883 | */ |
1863 | if (ret || mem_cgroup_check_under_limit(mem_over_limit)) | 1884 | if (csize == PAGE_SIZE && ret) |
1864 | return CHARGE_RETRY; | 1885 | return CHARGE_RETRY; |
1865 | 1886 | ||
1866 | /* | 1887 | /* |