diff options
Diffstat (limited to 'mm/nommu.c')
-rw-r--r-- | mm/nommu.c | 35 |
1 files changed, 30 insertions, 5 deletions
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 */ | |||
63 | int sysctl_overcommit_ratio = 50; /* default is 50% */ | 63 | int sysctl_overcommit_ratio = 50; /* default is 50% */ |
64 | int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; | 64 | int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; |
65 | int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS; | 65 | int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS; |
66 | unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */ | ||
66 | int heap_stack_gap = 0; | 67 | int heap_stack_gap = 0; |
67 | 68 | ||
68 | atomic_long_t mmap_pages_allocated; | 69 | atomic_long_t mmap_pages_allocated; |
@@ -1897,7 +1898,7 @@ EXPORT_SYMBOL(unmap_mapping_range); | |||
1897 | */ | 1898 | */ |
1898 | int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | 1899 | int __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 | */ | ||
2140 | static 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 | } | ||
2149 | module_init(init_user_reserve) | ||