diff options
Diffstat (limited to 'mm/mmap.c')
-rw-r--r-- | mm/mmap.c | 35 |
1 files changed, 30 insertions, 5 deletions
@@ -84,6 +84,7 @@ EXPORT_SYMBOL(vm_get_page_prot); | |||
84 | int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS; /* heuristic overcommit */ | 84 | int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS; /* heuristic overcommit */ |
85 | int sysctl_overcommit_ratio __read_mostly = 50; /* default is 50% */ | 85 | int sysctl_overcommit_ratio __read_mostly = 50; /* default is 50% */ |
86 | int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT; | 86 | int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT; |
87 | unsigned 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 | */ |
123 | int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | 124 | int __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 | */ | ||
3112 | static 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 | } | ||
3121 | module_init(init_user_reserve) | ||