diff options
author | Andrey Ryabinin <aryabinin@virtuozzo.com> | 2016-03-17 17:18:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-17 18:09:34 -0400 |
commit | 39a1aa8e194ab67983de3b9d0b204ccee12e689a (patch) | |
tree | 66e70a955436cd15a170b848fdba9563bf30cb37 /mm/mmap.c | |
parent | ea606cf5d8df370e7932460dfd960b21f20e7c6d (diff) |
mm: deduplicate memory overcommitment code
Currently we have two copies of the same code which implements memory
overcommitment logic. Let's move it into mm/util.c and hence avoid
duplication. No functional changes here.
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/mmap.c')
-rw-r--r-- | mm/mmap.c | 124 |
1 files changed, 0 insertions, 124 deletions
@@ -122,130 +122,6 @@ void vma_set_page_prot(struct vm_area_struct *vma) | |||
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 | ||
125 | |||
126 | int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS; /* heuristic overcommit */ | ||
127 | int sysctl_overcommit_ratio __read_mostly = 50; /* default is 50% */ | ||
128 | unsigned long sysctl_overcommit_kbytes __read_mostly; | ||
129 | int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT; | ||
130 | unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */ | ||
131 | unsigned long sysctl_admin_reserve_kbytes __read_mostly = 1UL << 13; /* 8MB */ | ||
132 | /* | ||
133 | * Make sure vm_committed_as in one cacheline and not cacheline shared with | ||
134 | * other variables. It can be updated by several CPUs frequently. | ||
135 | */ | ||
136 | struct percpu_counter vm_committed_as ____cacheline_aligned_in_smp; | ||
137 | |||
138 | /* | ||
139 | * The global memory commitment made in the system can be a metric | ||
140 | * that can be used to drive ballooning decisions when Linux is hosted | ||
141 | * as a guest. On Hyper-V, the host implements a policy engine for dynamically | ||
142 | * balancing memory across competing virtual machines that are hosted. | ||
143 | * Several metrics drive this policy engine including the guest reported | ||
144 | * memory commitment. | ||
145 | */ | ||
146 | unsigned long vm_memory_committed(void) | ||
147 | { | ||
148 | return percpu_counter_read_positive(&vm_committed_as); | ||
149 | } | ||
150 | EXPORT_SYMBOL_GPL(vm_memory_committed); | ||
151 | |||
152 | /* | ||
153 | * Check that a process has enough memory to allocate a new virtual | ||
154 | * mapping. 0 means there is enough memory for the allocation to | ||
155 | * succeed and -ENOMEM implies there is not. | ||
156 | * | ||
157 | * We currently support three overcommit policies, which are set via the | ||
158 | * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting | ||
159 | * | ||
160 | * Strict overcommit modes added 2002 Feb 26 by Alan Cox. | ||
161 | * Additional code 2002 Jul 20 by Robert Love. | ||
162 | * | ||
163 | * cap_sys_admin is 1 if the process has admin privileges, 0 otherwise. | ||
164 | * | ||
165 | * Note this is a helper function intended to be used by LSMs which | ||
166 | * wish to use this logic. | ||
167 | */ | ||
168 | int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | ||
169 | { | ||
170 | long free, allowed, reserve; | ||
171 | |||
172 | VM_WARN_ONCE(percpu_counter_read(&vm_committed_as) < | ||
173 | -(s64)vm_committed_as_batch * num_online_cpus(), | ||
174 | "memory commitment underflow"); | ||
175 | |||
176 | vm_acct_memory(pages); | ||
177 | |||
178 | /* | ||
179 | * Sometimes we want to use more memory than we have | ||
180 | */ | ||
181 | if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) | ||
182 | return 0; | ||
183 | |||
184 | if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { | ||
185 | free = global_page_state(NR_FREE_PAGES); | ||
186 | free += global_page_state(NR_FILE_PAGES); | ||
187 | |||
188 | /* | ||
189 | * shmem pages shouldn't be counted as free in this | ||
190 | * case, they can't be purged, only swapped out, and | ||
191 | * that won't affect the overall amount of available | ||
192 | * memory in the system. | ||
193 | */ | ||
194 | free -= global_page_state(NR_SHMEM); | ||
195 | |||
196 | free += get_nr_swap_pages(); | ||
197 | |||
198 | /* | ||
199 | * Any slabs which are created with the | ||
200 | * SLAB_RECLAIM_ACCOUNT flag claim to have contents | ||
201 | * which are reclaimable, under pressure. The dentry | ||
202 | * cache and most inode caches should fall into this | ||
203 | */ | ||
204 | free += global_page_state(NR_SLAB_RECLAIMABLE); | ||
205 | |||
206 | /* | ||
207 | * Leave reserved pages. The pages are not for anonymous pages. | ||
208 | */ | ||
209 | if (free <= totalreserve_pages) | ||
210 | goto error; | ||
211 | else | ||
212 | free -= totalreserve_pages; | ||
213 | |||
214 | /* | ||
215 | * Reserve some for root | ||
216 | */ | ||
217 | if (!cap_sys_admin) | ||
218 | free -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10); | ||
219 | |||
220 | if (free > pages) | ||
221 | return 0; | ||
222 | |||
223 | goto error; | ||
224 | } | ||
225 | |||
226 | allowed = vm_commit_limit(); | ||
227 | /* | ||
228 | * Reserve some for root | ||
229 | */ | ||
230 | if (!cap_sys_admin) | ||
231 | allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10); | ||
232 | |||
233 | /* | ||
234 | * Don't let a single process grow so big a user can't recover | ||
235 | */ | ||
236 | if (mm) { | ||
237 | reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10); | ||
238 | allowed -= min_t(long, mm->total_vm / 32, reserve); | ||
239 | } | ||
240 | |||
241 | if (percpu_counter_read_positive(&vm_committed_as) < allowed) | ||
242 | return 0; | ||
243 | error: | ||
244 | vm_unacct_memory(pages); | ||
245 | |||
246 | return -ENOMEM; | ||
247 | } | ||
248 | |||
249 | /* | 125 | /* |
250 | * Requires inode->i_mapping->i_mmap_rwsem | 126 | * Requires inode->i_mapping->i_mmap_rwsem |
251 | */ | 127 | */ |