diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-02-24 14:36:31 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-02-24 14:36:31 -0500 |
commit | f227e08b71b9c273eaa29a57370a3a5b833aa382 (patch) | |
tree | 9f1483776a2bde3bb1a6bd744e69acf19f6f3428 /mm/memcontrol.c | |
parent | fec38d1752c01ad72789bac9f1a128f7e933735d (diff) | |
parent | f5412be599602124d2bdd49947b231dd77c0bf99 (diff) |
Merge 2.6.38-rc6 into tty-next
This was to resolve a merge issue with drivers/char/Makefile and
drivers/tty/serial/68328serial.c
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r-- | mm/memcontrol.c | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3878cfe399dc..da53a252b259 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -612,8 +612,10 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *mem, | |||
612 | /* pagein of a big page is an event. So, ignore page size */ | 612 | /* pagein of a big page is an event. So, ignore page size */ |
613 | if (nr_pages > 0) | 613 | if (nr_pages > 0) |
614 | __this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGIN_COUNT]); | 614 | __this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGIN_COUNT]); |
615 | else | 615 | else { |
616 | __this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGOUT_COUNT]); | 616 | __this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGOUT_COUNT]); |
617 | nr_pages = -nr_pages; /* for event */ | ||
618 | } | ||
617 | 619 | ||
618 | __this_cpu_add(mem->stat->count[MEM_CGROUP_EVENTS], nr_pages); | 620 | __this_cpu_add(mem->stat->count[MEM_CGROUP_EVENTS], nr_pages); |
619 | 621 | ||
@@ -1111,6 +1113,23 @@ static bool mem_cgroup_check_under_limit(struct mem_cgroup *mem) | |||
1111 | return false; | 1113 | return false; |
1112 | } | 1114 | } |
1113 | 1115 | ||
1116 | /** | ||
1117 | * mem_cgroup_check_margin - check if the memory cgroup allows charging | ||
1118 | * @mem: memory cgroup to check | ||
1119 | * @bytes: the number of bytes the caller intends to charge | ||
1120 | * | ||
1121 | * Returns a boolean value on whether @mem can be charged @bytes or | ||
1122 | * whether this would exceed the limit. | ||
1123 | */ | ||
1124 | static bool mem_cgroup_check_margin(struct mem_cgroup *mem, unsigned long bytes) | ||
1125 | { | ||
1126 | if (!res_counter_check_margin(&mem->res, bytes)) | ||
1127 | return false; | ||
1128 | if (do_swap_account && !res_counter_check_margin(&mem->memsw, bytes)) | ||
1129 | return false; | ||
1130 | return true; | ||
1131 | } | ||
1132 | |||
1114 | static unsigned int get_swappiness(struct mem_cgroup *memcg) | 1133 | static unsigned int get_swappiness(struct mem_cgroup *memcg) |
1115 | { | 1134 | { |
1116 | struct cgroup *cgrp = memcg->css.cgroup; | 1135 | struct cgroup *cgrp = memcg->css.cgroup; |
@@ -1837,23 +1856,34 @@ static int __mem_cgroup_do_charge(struct mem_cgroup *mem, gfp_t gfp_mask, | |||
1837 | flags |= MEM_CGROUP_RECLAIM_NOSWAP; | 1856 | flags |= MEM_CGROUP_RECLAIM_NOSWAP; |
1838 | } else | 1857 | } else |
1839 | mem_over_limit = mem_cgroup_from_res_counter(fail_res, res); | 1858 | mem_over_limit = mem_cgroup_from_res_counter(fail_res, res); |
1840 | 1859 | /* | |
1841 | if (csize > PAGE_SIZE) /* change csize and retry */ | 1860 | * csize can be either a huge page (HPAGE_SIZE), a batch of |
1861 | * regular pages (CHARGE_SIZE), or a single regular page | ||
1862 | * (PAGE_SIZE). | ||
1863 | * | ||
1864 | * Never reclaim on behalf of optional batching, retry with a | ||
1865 | * single page instead. | ||
1866 | */ | ||
1867 | if (csize == CHARGE_SIZE) | ||
1842 | return CHARGE_RETRY; | 1868 | return CHARGE_RETRY; |
1843 | 1869 | ||
1844 | if (!(gfp_mask & __GFP_WAIT)) | 1870 | if (!(gfp_mask & __GFP_WAIT)) |
1845 | return CHARGE_WOULDBLOCK; | 1871 | return CHARGE_WOULDBLOCK; |
1846 | 1872 | ||
1847 | ret = mem_cgroup_hierarchical_reclaim(mem_over_limit, NULL, | 1873 | ret = mem_cgroup_hierarchical_reclaim(mem_over_limit, NULL, |
1848 | gfp_mask, flags); | 1874 | gfp_mask, flags); |
1875 | if (mem_cgroup_check_margin(mem_over_limit, csize)) | ||
1876 | return CHARGE_RETRY; | ||
1849 | /* | 1877 | /* |
1850 | * try_to_free_mem_cgroup_pages() might not give us a full | 1878 | * Even though the limit is exceeded at this point, reclaim |
1851 | * picture of reclaim. Some pages are reclaimed and might be | 1879 | * may have been able to free some pages. Retry the charge |
1852 | * moved to swap cache or just unmapped from the cgroup. | 1880 | * before killing the task. |
1853 | * Check the limit again to see if the reclaim reduced the | 1881 | * |
1854 | * current usage of the cgroup before giving up | 1882 | * Only for regular pages, though: huge pages are rather |
1883 | * unlikely to succeed so close to the limit, and we fall back | ||
1884 | * to regular pages anyway in case of failure. | ||
1855 | */ | 1885 | */ |
1856 | if (ret || mem_cgroup_check_under_limit(mem_over_limit)) | 1886 | if (csize == PAGE_SIZE && ret) |
1857 | return CHARGE_RETRY; | 1887 | return CHARGE_RETRY; |
1858 | 1888 | ||
1859 | /* | 1889 | /* |
@@ -2323,13 +2353,19 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, | |||
2323 | gfp_t gfp_mask, enum charge_type ctype) | 2353 | gfp_t gfp_mask, enum charge_type ctype) |
2324 | { | 2354 | { |
2325 | struct mem_cgroup *mem = NULL; | 2355 | struct mem_cgroup *mem = NULL; |
2356 | int page_size = PAGE_SIZE; | ||
2326 | struct page_cgroup *pc; | 2357 | struct page_cgroup *pc; |
2358 | bool oom = true; | ||
2327 | int ret; | 2359 | int ret; |
2328 | int page_size = PAGE_SIZE; | ||
2329 | 2360 | ||
2330 | if (PageTransHuge(page)) { | 2361 | if (PageTransHuge(page)) { |
2331 | page_size <<= compound_order(page); | 2362 | page_size <<= compound_order(page); |
2332 | VM_BUG_ON(!PageTransHuge(page)); | 2363 | VM_BUG_ON(!PageTransHuge(page)); |
2364 | /* | ||
2365 | * Never OOM-kill a process for a huge page. The | ||
2366 | * fault handler will fall back to regular pages. | ||
2367 | */ | ||
2368 | oom = false; | ||
2333 | } | 2369 | } |
2334 | 2370 | ||
2335 | pc = lookup_page_cgroup(page); | 2371 | pc = lookup_page_cgroup(page); |
@@ -2338,7 +2374,7 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, | |||
2338 | return 0; | 2374 | return 0; |
2339 | prefetchw(pc); | 2375 | prefetchw(pc); |
2340 | 2376 | ||
2341 | ret = __mem_cgroup_try_charge(mm, gfp_mask, &mem, true, page_size); | 2377 | ret = __mem_cgroup_try_charge(mm, gfp_mask, &mem, oom, page_size); |
2342 | if (ret || !mem) | 2378 | if (ret || !mem) |
2343 | return ret; | 2379 | return ret; |
2344 | 2380 | ||
@@ -5024,9 +5060,9 @@ struct cgroup_subsys mem_cgroup_subsys = { | |||
5024 | static int __init enable_swap_account(char *s) | 5060 | static int __init enable_swap_account(char *s) |
5025 | { | 5061 | { |
5026 | /* consider enabled if no parameter or 1 is given */ | 5062 | /* consider enabled if no parameter or 1 is given */ |
5027 | if (!s || !strcmp(s, "1")) | 5063 | if (!(*s) || !strcmp(s, "=1")) |
5028 | really_do_swap_account = 1; | 5064 | really_do_swap_account = 1; |
5029 | else if (!strcmp(s, "0")) | 5065 | else if (!strcmp(s, "=0")) |
5030 | really_do_swap_account = 0; | 5066 | really_do_swap_account = 0; |
5031 | return 1; | 5067 | return 1; |
5032 | } | 5068 | } |
@@ -5034,7 +5070,8 @@ __setup("swapaccount", enable_swap_account); | |||
5034 | 5070 | ||
5035 | static int __init disable_swap_account(char *s) | 5071 | static int __init disable_swap_account(char *s) |
5036 | { | 5072 | { |
5037 | enable_swap_account("0"); | 5073 | printk_once("noswapaccount is deprecated and will be removed in 2.6.40. Use swapaccount=0 instead\n"); |
5074 | enable_swap_account("=0"); | ||
5038 | return 1; | 5075 | return 1; |
5039 | } | 5076 | } |
5040 | __setup("noswapaccount", disable_swap_account); | 5077 | __setup("noswapaccount", disable_swap_account); |