aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/res_counter.h20
-rw-r--r--mm/memcontrol.c35
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 */
193static 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
185static inline bool res_counter_check_under_soft_limit(struct res_counter *cnt) 205static 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 */
1122static 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
1114static unsigned int get_swappiness(struct mem_cgroup *memcg) 1131static 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 /*