aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/rmap.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/mm/rmap.c b/mm/rmap.c
index f286697c61dc..68756a77ef87 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -324,36 +324,43 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
324 return -ENOMEM; 324 return -ENOMEM;
325} 325}
326 326
327static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain)
328{
329 struct anon_vma *anon_vma = anon_vma_chain->anon_vma;
330 int empty;
331
332 /* If anon_vma_fork fails, we can get an empty anon_vma_chain. */
333 if (!anon_vma)
334 return;
335
336 anon_vma_lock(anon_vma);
337 list_del(&anon_vma_chain->same_anon_vma);
338
339 /* We must garbage collect the anon_vma if it's empty */
340 empty = list_empty(&anon_vma->head);
341 anon_vma_unlock(anon_vma);
342
343 if (empty)
344 put_anon_vma(anon_vma);
345}
346
347void unlink_anon_vmas(struct vm_area_struct *vma) 327void unlink_anon_vmas(struct vm_area_struct *vma)
348{ 328{
349 struct anon_vma_chain *avc, *next; 329 struct anon_vma_chain *avc, *next;
330 struct anon_vma *root = NULL;
350 331
351 /* 332 /*
352 * Unlink each anon_vma chained to the VMA. This list is ordered 333 * Unlink each anon_vma chained to the VMA. This list is ordered
353 * from newest to oldest, ensuring the root anon_vma gets freed last. 334 * from newest to oldest, ensuring the root anon_vma gets freed last.
354 */ 335 */
355 list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { 336 list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
356 anon_vma_unlink(avc); 337 struct anon_vma *anon_vma = avc->anon_vma;
338
339 root = lock_anon_vma_root(root, anon_vma);
340 list_del(&avc->same_anon_vma);
341
342 /*
343 * Leave empty anon_vmas on the list - we'll need
344 * to free them outside the lock.
345 */
346 if (list_empty(&anon_vma->head))
347 continue;
348
349 list_del(&avc->same_vma);
350 anon_vma_chain_free(avc);
351 }
352 unlock_anon_vma_root(root);
353
354 /*
355 * Iterate the list once more, it now only contains empty and unlinked
356 * anon_vmas, destroy them. Could not do before due to __put_anon_vma()
357 * needing to acquire the anon_vma->root->mutex.
358 */
359 list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
360 struct anon_vma *anon_vma = avc->anon_vma;
361
362 put_anon_vma(anon_vma);
363
357 list_del(&avc->same_vma); 364 list_del(&avc->same_vma);
358 anon_vma_chain_free(avc); 365 anon_vma_chain_free(avc);
359 } 366 }