diff options
Diffstat (limited to 'mm/rmap.c')
-rw-r--r-- | mm/rmap.c | 106 |
1 files changed, 75 insertions, 31 deletions
@@ -112,9 +112,9 @@ static inline void anon_vma_free(struct anon_vma *anon_vma) | |||
112 | kmem_cache_free(anon_vma_cachep, anon_vma); | 112 | kmem_cache_free(anon_vma_cachep, anon_vma); |
113 | } | 113 | } |
114 | 114 | ||
115 | static inline struct anon_vma_chain *anon_vma_chain_alloc(void) | 115 | static inline struct anon_vma_chain *anon_vma_chain_alloc(gfp_t gfp) |
116 | { | 116 | { |
117 | return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL); | 117 | return kmem_cache_alloc(anon_vma_chain_cachep, gfp); |
118 | } | 118 | } |
119 | 119 | ||
120 | static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain) | 120 | static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain) |
@@ -159,7 +159,7 @@ int anon_vma_prepare(struct vm_area_struct *vma) | |||
159 | struct mm_struct *mm = vma->vm_mm; | 159 | struct mm_struct *mm = vma->vm_mm; |
160 | struct anon_vma *allocated; | 160 | struct anon_vma *allocated; |
161 | 161 | ||
162 | avc = anon_vma_chain_alloc(); | 162 | avc = anon_vma_chain_alloc(GFP_KERNEL); |
163 | if (!avc) | 163 | if (!avc) |
164 | goto out_enomem; | 164 | goto out_enomem; |
165 | 165 | ||
@@ -200,6 +200,32 @@ int anon_vma_prepare(struct vm_area_struct *vma) | |||
200 | return -ENOMEM; | 200 | return -ENOMEM; |
201 | } | 201 | } |
202 | 202 | ||
203 | /* | ||
204 | * This is a useful helper function for locking the anon_vma root as | ||
205 | * we traverse the vma->anon_vma_chain, looping over anon_vma's that | ||
206 | * have the same vma. | ||
207 | * | ||
208 | * Such anon_vma's should have the same root, so you'd expect to see | ||
209 | * just a single mutex_lock for the whole traversal. | ||
210 | */ | ||
211 | static inline struct anon_vma *lock_anon_vma_root(struct anon_vma *root, struct anon_vma *anon_vma) | ||
212 | { | ||
213 | struct anon_vma *new_root = anon_vma->root; | ||
214 | if (new_root != root) { | ||
215 | if (WARN_ON_ONCE(root)) | ||
216 | mutex_unlock(&root->mutex); | ||
217 | root = new_root; | ||
218 | mutex_lock(&root->mutex); | ||
219 | } | ||
220 | return root; | ||
221 | } | ||
222 | |||
223 | static inline void unlock_anon_vma_root(struct anon_vma *root) | ||
224 | { | ||
225 | if (root) | ||
226 | mutex_unlock(&root->mutex); | ||
227 | } | ||
228 | |||
203 | static void anon_vma_chain_link(struct vm_area_struct *vma, | 229 | static void anon_vma_chain_link(struct vm_area_struct *vma, |
204 | struct anon_vma_chain *avc, | 230 | struct anon_vma_chain *avc, |
205 | struct anon_vma *anon_vma) | 231 | struct anon_vma *anon_vma) |
@@ -208,13 +234,11 @@ static void anon_vma_chain_link(struct vm_area_struct *vma, | |||
208 | avc->anon_vma = anon_vma; | 234 | avc->anon_vma = anon_vma; |
209 | list_add(&avc->same_vma, &vma->anon_vma_chain); | 235 | list_add(&avc->same_vma, &vma->anon_vma_chain); |
210 | 236 | ||
211 | anon_vma_lock(anon_vma); | ||
212 | /* | 237 | /* |
213 | * It's critical to add new vmas to the tail of the anon_vma, | 238 | * It's critical to add new vmas to the tail of the anon_vma, |
214 | * see comment in huge_memory.c:__split_huge_page(). | 239 | * see comment in huge_memory.c:__split_huge_page(). |
215 | */ | 240 | */ |
216 | list_add_tail(&avc->same_anon_vma, &anon_vma->head); | 241 | list_add_tail(&avc->same_anon_vma, &anon_vma->head); |
217 | anon_vma_unlock(anon_vma); | ||
218 | } | 242 | } |
219 | 243 | ||
220 | /* | 244 | /* |
@@ -224,13 +248,24 @@ static void anon_vma_chain_link(struct vm_area_struct *vma, | |||
224 | int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) | 248 | int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) |
225 | { | 249 | { |
226 | struct anon_vma_chain *avc, *pavc; | 250 | struct anon_vma_chain *avc, *pavc; |
251 | struct anon_vma *root = NULL; | ||
227 | 252 | ||
228 | list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) { | 253 | list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) { |
229 | avc = anon_vma_chain_alloc(); | 254 | struct anon_vma *anon_vma; |
230 | if (!avc) | 255 | |
231 | goto enomem_failure; | 256 | avc = anon_vma_chain_alloc(GFP_NOWAIT | __GFP_NOWARN); |
232 | anon_vma_chain_link(dst, avc, pavc->anon_vma); | 257 | if (unlikely(!avc)) { |
258 | unlock_anon_vma_root(root); | ||
259 | root = NULL; | ||
260 | avc = anon_vma_chain_alloc(GFP_KERNEL); | ||
261 | if (!avc) | ||
262 | goto enomem_failure; | ||
263 | } | ||
264 | anon_vma = pavc->anon_vma; | ||
265 | root = lock_anon_vma_root(root, anon_vma); | ||
266 | anon_vma_chain_link(dst, avc, anon_vma); | ||
233 | } | 267 | } |
268 | unlock_anon_vma_root(root); | ||
234 | return 0; | 269 | return 0; |
235 | 270 | ||
236 | enomem_failure: | 271 | enomem_failure: |
@@ -263,7 +298,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) | |||
263 | anon_vma = anon_vma_alloc(); | 298 | anon_vma = anon_vma_alloc(); |
264 | if (!anon_vma) | 299 | if (!anon_vma) |
265 | goto out_error; | 300 | goto out_error; |
266 | avc = anon_vma_chain_alloc(); | 301 | avc = anon_vma_chain_alloc(GFP_KERNEL); |
267 | if (!avc) | 302 | if (!avc) |
268 | goto out_error_free_anon_vma; | 303 | goto out_error_free_anon_vma; |
269 | 304 | ||
@@ -280,7 +315,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) | |||
280 | get_anon_vma(anon_vma->root); | 315 | get_anon_vma(anon_vma->root); |
281 | /* Mark this anon_vma as the one where our new (COWed) pages go. */ | 316 | /* Mark this anon_vma as the one where our new (COWed) pages go. */ |
282 | vma->anon_vma = anon_vma; | 317 | vma->anon_vma = anon_vma; |
318 | anon_vma_lock(anon_vma); | ||
283 | anon_vma_chain_link(vma, avc, anon_vma); | 319 | anon_vma_chain_link(vma, avc, anon_vma); |
320 | anon_vma_unlock(anon_vma); | ||
284 | 321 | ||
285 | return 0; | 322 | return 0; |
286 | 323 | ||
@@ -291,36 +328,43 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) | |||
291 | return -ENOMEM; | 328 | return -ENOMEM; |
292 | } | 329 | } |
293 | 330 | ||
294 | static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain) | ||
295 | { | ||
296 | struct anon_vma *anon_vma = anon_vma_chain->anon_vma; | ||
297 | int empty; | ||
298 | |||
299 | /* If anon_vma_fork fails, we can get an empty anon_vma_chain. */ | ||
300 | if (!anon_vma) | ||
301 | return; | ||
302 | |||
303 | anon_vma_lock(anon_vma); | ||
304 | list_del(&anon_vma_chain->same_anon_vma); | ||
305 | |||
306 | /* We must garbage collect the anon_vma if it's empty */ | ||
307 | empty = list_empty(&anon_vma->head); | ||
308 | anon_vma_unlock(anon_vma); | ||
309 | |||
310 | if (empty) | ||
311 | put_anon_vma(anon_vma); | ||
312 | } | ||
313 | |||
314 | void unlink_anon_vmas(struct vm_area_struct *vma) | 331 | void unlink_anon_vmas(struct vm_area_struct *vma) |
315 | { | 332 | { |
316 | struct anon_vma_chain *avc, *next; | 333 | struct anon_vma_chain *avc, *next; |
334 | struct anon_vma *root = NULL; | ||
317 | 335 | ||
318 | /* | 336 | /* |
319 | * Unlink each anon_vma chained to the VMA. This list is ordered | 337 | * Unlink each anon_vma chained to the VMA. This list is ordered |
320 | * from newest to oldest, ensuring the root anon_vma gets freed last. | 338 | * from newest to oldest, ensuring the root anon_vma gets freed last. |
321 | */ | 339 | */ |
322 | list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { | 340 | list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { |
323 | anon_vma_unlink(avc); | 341 | struct anon_vma *anon_vma = avc->anon_vma; |
342 | |||
343 | root = lock_anon_vma_root(root, anon_vma); | ||
344 | list_del(&avc->same_anon_vma); | ||
345 | |||
346 | /* | ||
347 | * Leave empty anon_vmas on the list - we'll need | ||
348 | * to free them outside the lock. | ||
349 | */ | ||
350 | if (list_empty(&anon_vma->head)) | ||
351 | continue; | ||
352 | |||
353 | list_del(&avc->same_vma); | ||
354 | anon_vma_chain_free(avc); | ||
355 | } | ||
356 | unlock_anon_vma_root(root); | ||
357 | |||
358 | /* | ||
359 | * Iterate the list once more, it now only contains empty and unlinked | ||
360 | * anon_vmas, destroy them. Could not do before due to __put_anon_vma() | ||
361 | * needing to acquire the anon_vma->root->mutex. | ||
362 | */ | ||
363 | list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { | ||
364 | struct anon_vma *anon_vma = avc->anon_vma; | ||
365 | |||
366 | put_anon_vma(anon_vma); | ||
367 | |||
324 | list_del(&avc->same_vma); | 368 | list_del(&avc->same_vma); |
325 | anon_vma_chain_free(avc); | 369 | anon_vma_chain_free(avc); |
326 | } | 370 | } |