aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Shewmaker <agshew@gmail.com>2013-04-29 18:08:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-29 18:54:36 -0400
commitc9b1d0981fcce3d9976d7b7a56e4e0503bc610dd (patch)
treef7adfbfb1e34b3727e7d6b63a1ece93b358f87d8
parentd8f10cb3d375c34ad668f32ca6e4661ad1fc23b2 (diff)
mm: limit growth of 3% hardcoded other user reserve
Add user_reserve_kbytes knob. Limit the growth of the memory reserved for other user processes to min(3% current process size, user_reserve_pages). Only about 8MB is necessary to enable recovery in the default mode, and only a few hundred MB are required even when overcommit is disabled. user_reserve_pages defaults to min(3% free pages, 128MB) I arrived at 128MB by taking the max VSZ of sshd, login, bash, and top ... then adding the RSS of each. This only affects OVERCOMMIT_NEVER mode. Background 1. user reserve __vm_enough_memory reserves a hardcoded 3% of the current process size for other applications when overcommit is disabled. This was done so that a user could recover if they launched a memory hogging process. Without the reserve, a user would easily run into a message such as: bash: fork: Cannot allocate memory 2. admin reserve Additionally, a hardcoded 3% of free memory is reserved for root in both overcommit 'guess' and 'never' modes. This was intended to prevent a scenario where root-cant-log-in and perform recovery operations. Note that this reserve shrinks, and doesn't guarantee a useful reserve. Motivation The two hardcoded memory reserves should be updated to account for current memory sizes. Also, the admin reserve would be more useful if it didn't shrink too much. When the current code was originally written, 1GB was considered "enterprise". Now the 3% reserve can grow to multiple GB on large memory systems, and it only needs to be a few hundred MB at most to enable a user or admin to recover a system with an unwanted memory hogging process. I've found that reducing these reserves is especially beneficial for a specific type of application load: * single application system * one or few processes (e.g. one per core) * allocating all available memory * not initializing every page immediately * long running I've run scientific clusters with this sort of load. A long running job sometimes failed many hours (weeks of CPU time) into a calculation. They weren't initializing all of their memory immediately, and they weren't using calloc, so I put systems into overcommit 'never' mode. These clusters run diskless and have no swap. However, with the current reserves, a user wishing to allocate as much memory as possible to one process may be prevented from using, for example, almost 2GB out of 32GB. The effect is less, but still significant when a user starts a job with one process per core. I have repeatedly seen a set of processes requesting the same amount of memory fail because one of them could not allocate the amount of memory a user would expect to be able to allocate. For example, Message Passing Interfce (MPI) processes, one per core. And it is similar for other parallel programming frameworks. Changing this reserve code will make the overcommit never mode more useful by allowing applications to allocate nearly all of the available memory. Also, the new admin_reserve_kbytes will be safer than the current behavior since the hardcoded 3% of available memory reserve can shrink to something useless in the case where applications have grabbed all available memory. Risks * "bash: fork: Cannot allocate memory" The downside of the first patch-- which creates a tunable user reserve that is only used in overcommit 'never' mode--is that an admin can set it so low that a user may not be able to kill their process, even if they already have a shell prompt. Of course, a user can get in the same predicament with the current 3% reserve--they just have to launch processes until 3% becomes negligible. * root-cant-log-in problem The second patch, adding the tunable rootuser_reserve_pages, allows the admin to shoot themselves in the foot by setting it too small. They can easily get the system into a state where root-can't-log-in. However, the new admin_reserve_kbytes will be safer than the current behavior since the hardcoded 3% of available memory reserve can shrink to something useless in the case where applications have grabbed all available memory. Alternatives * Memory cgroups provide a more flexible way to limit application memory. Not everyone wants to set up cgroups or deal with their overhead. * We could create a fourth overcommit mode which provides smaller reserves. The size of useful reserves may be drastically different depending on the whether the system is embedded or enterprise. * Force users to initialize all of their memory or use calloc. Some users don't want/expect the system to overcommit when they malloc. Overcommit 'never' mode is for this scenario, and it should work well. The new user and admin reserve tunables are simple to use, with low overhead compared to cgroups. The patches preserve current behavior where 3% of memory is less than 128MB, except that the admin reserve doesn't shrink to an unusable size under pressure. The code allows admins to tune for embedded and enterprise usage. FAQ * How is the root-cant-login problem addressed? What happens if admin_reserve_pages is set to 0? Root is free to shoot themselves in the foot by setting admin_reserve_kbytes too low. On x86_64, the minimum useful reserve is: 8MB for overcommit 'guess' 128MB for overcommit 'never' admin_reserve_pages defaults to min(3% free memory, 8MB) So, anyone switching to 'never' mode needs to adjust admin_reserve_pages. * How do you calculate a minimum useful reserve? A user or the admin needs enough memory to login and perform recovery operations, which includes, at a minimum: sshd or login + bash (or some other shell) + top (or ps, kill, etc.) For overcommit 'guess', we can sum resident set sizes (RSS) because we only need enough memory to handle what the recovery programs will typically use. On x86_64 this is about 8MB. For overcommit 'never', we can take the max of their virtual sizes (VSZ) and add the sum of their RSS. We use VSZ instead of RSS because mode forces us to ensure we can fulfill all of the requested memory allocations-- even if the programs only use a fraction of what they ask for. On x86_64 this is about 128MB. When swap is enabled, reserves are useful even when they are as small as 10MB, regardless of overcommit mode. When both swap and overcommit are disabled, then the admin should tune the reserves higher to be absolutley safe. Over 230MB each was safest in my testing. * What happens if user_reserve_pages is set to 0? Note, this only affects overcomitt 'never' mode. Then a user will be able to allocate all available memory minus admin_reserve_kbytes. However, they will easily see a message such as: "bash: fork: Cannot allocate memory" And they won't be able to recover/kill their application. The admin should be able to recover the system if admin_reserve_kbytes is set appropriately. * What's the difference between overcommit 'guess' and 'never'? "Guess" allows an allocation if there are enough free + reclaimable pages. It has a hardcoded 3% of free pages reserved for root. "Never" allows an allocation if there is enough swap + a configurable percentage (default is 50) of physical RAM. It has a hardcoded 3% of free pages reserved for root, like "Guess" mode. It also has a hardcoded 3% of the current process size reserved for additional applications. * Why is overcommit 'guess' not suitable even when an app eventually writes to every page? It takes free pages, file pages, available swap pages, reclaimable slab pages into consideration. In other words, these are all pages available, then why isn't overcommit suitable? Because it only looks at the present state of the system. It does not take into account the memory that other applications have malloced, but haven't initialized yet. It overcommits the system. Test Summary There was little change in behavior in the default overcommit 'guess' mode with swap enabled before and after the patch. This was expected. Systems run most predictably (i.e. no oom kills) in overcommit 'never' mode with swap enabled. This also allowed the most memory to be allocated to a user application. Overcommit 'guess' mode without swap is a bad idea. It is easy to crash the system. None of the other tested combinations crashed. This matches my experience on the Roadrunner supercomputer. Without the tunable user reserve, a system in overcommit 'never' mode and without swap does not allow the admin to recover, although the admin can. With the new tunable reserves, a system in overcommit 'never' mode and without swap can be configured to: 1. maximize user-allocatable memory, running close to the edge of recoverability 2. maximize recoverability, sacrificing allocatable memory to ensure that a user cannot take down a system Test Description Fedora 18 VM - 4 x86_64 cores, 5725MB RAM, 4GB Swap System is booted into multiuser console mode, with unnecessary services turned off. Caches were dropped before each test. Hogs are user memtester processes that attempt to allocate all free memory as reported by /proc/meminfo In overcommit 'never' mode, memory_ratio=100 Test Results 3.9.0-rc1-mm1 Overcommit | Swap | Hogs | MB Got/Wanted | OOMs | User Recovery | Admin Recovery ---------- ---- ---- ------------- ---- ------------- -------------- guess yes 1 5432/5432 no yes yes guess yes 4 5444/5444 1 yes yes guess no 1 5302/5449 no yes yes guess no 4 - crash no no never yes 1 5460/5460 1 yes yes never yes 4 5460/5460 1 yes yes never no 1 5218/5432 no no yes never no 4 5203/5448 no no yes 3.9.0-rc1-mm1-tunablereserves User and Admin Recovery show their respective reserves, if applicable. Overcommit | Swap | Hogs | MB Got/Wanted | OOMs | User Recovery | Admin Recovery ---------- ---- ---- ------------- ---- ------------- -------------- guess yes 1 5419/5419 no - yes 8MB yes guess yes 4 5436/5436 1 - yes 8MB yes guess no 1 5440/5440 * - yes 8MB yes guess no 4 - crash - no 8MB no * process would successfully mlock, then the oom killer would pick it never yes 1 5446/5446 no 10MB yes 20MB yes never yes 4 5456/5456 no 10MB yes 20MB yes never no 1 5387/5429 no 128MB no 8MB barely never no 1 5323/5428 no 226MB barely 8MB barely never no 1 5323/5428 no 226MB barely 8MB barely never no 1 5359/5448 no 10MB no 10MB barely never no 1 5323/5428 no 0MB no 10MB barely never no 1 5332/5428 no 0MB no 50MB yes never no 1 5293/5429 no 0MB no 90MB yes never no 1 5001/5427 no 230MB yes 338MB yes never no 4* 4998/5424 no 230MB yes 338MB yes * more memtesters were launched, able to allocate approximately another 100MB Future Work - Test larger memory systems. - Test an embedded image. - Test other architectures. - Time malloc microbenchmarks. - Would it be useful to be able to set overcommit policy for each memory cgroup? - Some lines are slightly above 80 chars. Perhaps define a macro to convert between pages and kb? Other places in the kernel do this. [akpm@linux-foundation.org: coding-style fixes] [akpm@linux-foundation.org: make init_user_reserve() static] Signed-off-by: Andrew Shewmaker <agshew@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/sysctl/vm.txt20
-rw-r--r--Documentation/vm/overcommit-accounting8
-rw-r--r--include/linux/mm.h2
-rw-r--r--kernel/sysctl.c7
-rw-r--r--mm/mmap.c35
-rw-r--r--mm/nommu.c35
6 files changed, 96 insertions, 11 deletions
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 078701fdbd4d..f69895738357 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -53,6 +53,7 @@ Currently, these files are in /proc/sys/vm:
53- percpu_pagelist_fraction 53- percpu_pagelist_fraction
54- stat_interval 54- stat_interval
55- swappiness 55- swappiness
56- user_reserve_kbytes
56- vfs_cache_pressure 57- vfs_cache_pressure
57- zone_reclaim_mode 58- zone_reclaim_mode
58 59
@@ -542,6 +543,7 @@ memory until it actually runs out.
542 543
543When this flag is 2, the kernel uses a "never overcommit" 544When this flag is 2, the kernel uses a "never overcommit"
544policy that attempts to prevent any overcommit of memory. 545policy that attempts to prevent any overcommit of memory.
546Note that user_reserve_kbytes affects this policy.
545 547
546This feature can be very useful because there are a lot of 548This feature can be very useful because there are a lot of
547programs that malloc() huge amounts of memory "just-in-case" 549programs that malloc() huge amounts of memory "just-in-case"
@@ -645,6 +647,24 @@ The default value is 60.
645 647
646============================================================== 648==============================================================
647 649
650- user_reserve_kbytes
651
652When overcommit_memory is set to 2, "never overommit" mode, reserve
653min(3% of current process size, user_reserve_kbytes) of free memory.
654This is intended to prevent a user from starting a single memory hogging
655process, such that they cannot recover (kill the hog).
656
657user_reserve_kbytes defaults to min(3% of the current process size, 128MB).
658
659If this is reduced to zero, then the user will be allowed to allocate
660all free memory with a single process, minus admin_reserve_kbytes.
661Any subsequent attempts to execute a command will result in
662"fork: Cannot allocate memory".
663
664Changing this takes effect whenever an application requests memory.
665
666==============================================================
667
648vfs_cache_pressure 668vfs_cache_pressure
649------------------ 669------------------
650 670
diff --git a/Documentation/vm/overcommit-accounting b/Documentation/vm/overcommit-accounting
index 706d7ed9d8d2..8eaa2fc4b8fa 100644
--- a/Documentation/vm/overcommit-accounting
+++ b/Documentation/vm/overcommit-accounting
@@ -8,7 +8,9 @@ The Linux kernel supports the following overcommit handling modes
8 default. 8 default.
9 9
101 - Always overcommit. Appropriate for some scientific 101 - Always overcommit. Appropriate for some scientific
11 applications. 11 applications. Classic example is code using sparse arrays
12 and just relying on the virtual memory consisting almost
13 entirely of zero pages.
12 14
132 - Don't overcommit. The total address space commit 152 - Don't overcommit. The total address space commit
14 for the system is not permitted to exceed swap + a 16 for the system is not permitted to exceed swap + a
@@ -18,6 +20,10 @@ The Linux kernel supports the following overcommit handling modes
18 pages but will receive errors on memory allocation as 20 pages but will receive errors on memory allocation as
19 appropriate. 21 appropriate.
20 22
23 Useful for applications that want to guarantee their
24 memory allocations will be available in the future
25 without having to initialize every page.
26
21The overcommit policy is set via the sysctl `vm.overcommit_memory'. 27The overcommit policy is set via the sysctl `vm.overcommit_memory'.
22 28
23The overcommit percentage is set via `vm.overcommit_ratio'. 29The overcommit percentage is set via `vm.overcommit_ratio'.
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 7aa11a6736eb..43cfaabbde40 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -44,6 +44,8 @@ extern int sysctl_legacy_va_layout;
44#include <asm/pgtable.h> 44#include <asm/pgtable.h>
45#include <asm/processor.h> 45#include <asm/processor.h>
46 46
47extern unsigned long sysctl_user_reserve_kbytes;
48
47#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n)) 49#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
48 50
49/* to align the pointer to the (next) page boundary */ 51/* to align the pointer to the (next) page boundary */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 3dadde52253c..6daabb72bdb5 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1429,6 +1429,13 @@ static struct ctl_table vm_table[] = {
1429 .extra2 = &one, 1429 .extra2 = &one,
1430 }, 1430 },
1431#endif 1431#endif
1432 {
1433 .procname = "user_reserve_kbytes",
1434 .data = &sysctl_user_reserve_kbytes,
1435 .maxlen = sizeof(sysctl_user_reserve_kbytes),
1436 .mode = 0644,
1437 .proc_handler = proc_doulongvec_minmax,
1438 },
1432 { } 1439 { }
1433}; 1440};
1434 1441
diff --git a/mm/mmap.c b/mm/mmap.c
index 081e6da8e1a4..80a965f35251 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -84,6 +84,7 @@ EXPORT_SYMBOL(vm_get_page_prot);
84int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS; /* heuristic overcommit */ 84int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS; /* heuristic overcommit */
85int sysctl_overcommit_ratio __read_mostly = 50; /* default is 50% */ 85int sysctl_overcommit_ratio __read_mostly = 50; /* default is 50% */
86int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT; 86int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
87unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */
87/* 88/*
88 * Make sure vm_committed_as in one cacheline and not cacheline shared with 89 * Make sure vm_committed_as in one cacheline and not cacheline shared with
89 * other variables. It can be updated by several CPUs frequently. 90 * other variables. It can be updated by several CPUs frequently.
@@ -122,7 +123,7 @@ EXPORT_SYMBOL_GPL(vm_memory_committed);
122 */ 123 */
123int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) 124int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
124{ 125{
125 unsigned long free, allowed; 126 unsigned long free, allowed, reserve;
126 127
127 vm_acct_memory(pages); 128 vm_acct_memory(pages);
128 129
@@ -183,10 +184,13 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
183 allowed -= allowed / 32; 184 allowed -= allowed / 32;
184 allowed += total_swap_pages; 185 allowed += total_swap_pages;
185 186
186 /* Don't let a single process grow too big: 187 /*
187 leave 3% of the size of this process for other processes */ 188 * Don't let a single process grow so big a user can't recover
188 if (mm) 189 */
189 allowed -= mm->total_vm / 32; 190 if (mm) {
191 reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
192 allowed -= min(mm->total_vm / 32, reserve);
193 }
190 194
191 if (percpu_counter_read_positive(&vm_committed_as) < allowed) 195 if (percpu_counter_read_positive(&vm_committed_as) < allowed)
192 return 0; 196 return 0;
@@ -3094,3 +3098,24 @@ void __init mmap_init(void)
3094 ret = percpu_counter_init(&vm_committed_as, 0); 3098 ret = percpu_counter_init(&vm_committed_as, 0);
3095 VM_BUG_ON(ret); 3099 VM_BUG_ON(ret);
3096} 3100}
3101
3102/*
3103 * Initialise sysctl_user_reserve_kbytes.
3104 *
3105 * This is intended to prevent a user from starting a single memory hogging
3106 * process, such that they cannot recover (kill the hog) in OVERCOMMIT_NEVER
3107 * mode.
3108 *
3109 * The default value is min(3% of free memory, 128MB)
3110 * 128MB is enough to recover with sshd/login, bash, and top/kill.
3111 */
3112static int __meminit init_user_reserve(void)
3113{
3114 unsigned long free_kbytes;
3115
3116 free_kbytes = global_page_state(NR_FREE_PAGES) << (PAGE_SHIFT - 10);
3117
3118 sysctl_user_reserve_kbytes = min(free_kbytes / 32, 1UL << 17);
3119 return 0;
3120}
3121module_init(init_user_reserve)
diff --git a/mm/nommu.c b/mm/nommu.c
index 2f1c75ed468e..58e4a0a5125f 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -63,6 +63,7 @@ int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
63int sysctl_overcommit_ratio = 50; /* default is 50% */ 63int sysctl_overcommit_ratio = 50; /* default is 50% */
64int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; 64int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
65int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS; 65int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS;
66unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */
66int heap_stack_gap = 0; 67int heap_stack_gap = 0;
67 68
68atomic_long_t mmap_pages_allocated; 69atomic_long_t mmap_pages_allocated;
@@ -1897,7 +1898,7 @@ EXPORT_SYMBOL(unmap_mapping_range);
1897 */ 1898 */
1898int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) 1899int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
1899{ 1900{
1900 unsigned long free, allowed; 1901 unsigned long free, allowed, reserve;
1901 1902
1902 vm_acct_memory(pages); 1903 vm_acct_memory(pages);
1903 1904
@@ -1957,10 +1958,13 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
1957 allowed -= allowed / 32; 1958 allowed -= allowed / 32;
1958 allowed += total_swap_pages; 1959 allowed += total_swap_pages;
1959 1960
1960 /* Don't let a single process grow too big: 1961 /*
1961 leave 3% of the size of this process for other processes */ 1962 * Don't let a single process grow so big a user can't recover
1962 if (mm) 1963 */
1963 allowed -= mm->total_vm / 32; 1964 if (mm) {
1965 reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
1966 allowed -= min(mm->total_vm / 32, reserve);
1967 }
1964 1968
1965 if (percpu_counter_read_positive(&vm_committed_as) < allowed) 1969 if (percpu_counter_read_positive(&vm_committed_as) < allowed)
1966 return 0; 1970 return 0;
@@ -2122,3 +2126,24 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size,
2122 up_write(&nommu_region_sem); 2126 up_write(&nommu_region_sem);
2123 return 0; 2127 return 0;
2124} 2128}
2129
2130/*
2131 * Initialise sysctl_user_reserve_kbytes.
2132 *
2133 * This is intended to prevent a user from starting a single memory hogging
2134 * process, such that they cannot recover (kill the hog) in OVERCOMMIT_NEVER
2135 * mode.
2136 *
2137 * The default value is min(3% of free memory, 128MB)
2138 * 128MB is enough to recover with sshd/login, bash, and top/kill.
2139 */
2140static int __meminit init_user_reserve(void)
2141{
2142 unsigned long free_kbytes;
2143
2144 free_kbytes = global_page_state(NR_FREE_PAGES) << (PAGE_SHIFT - 10);
2145
2146 sysctl_user_reserve_kbytes = min(free_kbytes / 32, 1UL << 17);
2147 return 0;
2148}
2149module_init(init_user_reserve)