diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/migrate.c | 48 |
1 files changed, 19 insertions, 29 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index 89a6bc8cd307..a20cf12edede 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
| @@ -622,7 +622,6 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
| 622 | int *result = NULL; | 622 | int *result = NULL; |
| 623 | struct page *newpage = get_new_page(page, private, &result); | 623 | struct page *newpage = get_new_page(page, private, &result); |
| 624 | int remap_swapcache = 1; | 624 | int remap_swapcache = 1; |
| 625 | int rcu_locked = 0; | ||
| 626 | int charge = 0; | 625 | int charge = 0; |
| 627 | struct mem_cgroup *mem = NULL; | 626 | struct mem_cgroup *mem = NULL; |
| 628 | struct anon_vma *anon_vma = NULL; | 627 | struct anon_vma *anon_vma = NULL; |
| @@ -694,20 +693,26 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
| 694 | /* | 693 | /* |
| 695 | * By try_to_unmap(), page->mapcount goes down to 0 here. In this case, | 694 | * By try_to_unmap(), page->mapcount goes down to 0 here. In this case, |
| 696 | * we cannot notice that anon_vma is freed while we migrates a page. | 695 | * we cannot notice that anon_vma is freed while we migrates a page. |
| 697 | * This rcu_read_lock() delays freeing anon_vma pointer until the end | 696 | * This get_anon_vma() delays freeing anon_vma pointer until the end |
| 698 | * of migration. File cache pages are no problem because of page_lock() | 697 | * of migration. File cache pages are no problem because of page_lock() |
| 699 | * File Caches may use write_page() or lock_page() in migration, then, | 698 | * File Caches may use write_page() or lock_page() in migration, then, |
| 700 | * just care Anon page here. | 699 | * just care Anon page here. |
| 701 | */ | 700 | */ |
| 702 | if (PageAnon(page)) { | 701 | if (PageAnon(page)) { |
| 703 | rcu_read_lock(); | 702 | /* |
| 704 | rcu_locked = 1; | 703 | * Only page_lock_anon_vma() understands the subtleties of |
| 705 | 704 | * getting a hold on an anon_vma from outside one of its mms. | |
| 706 | /* Determine how to safely use anon_vma */ | 705 | */ |
| 707 | if (!page_mapped(page)) { | 706 | anon_vma = page_lock_anon_vma(page); |
| 708 | if (!PageSwapCache(page)) | 707 | if (anon_vma) { |
| 709 | goto rcu_unlock; | 708 | /* |
| 710 | 709 | * Take a reference count on the anon_vma if the | |
| 710 | * page is mapped so that it is guaranteed to | ||
| 711 | * exist when the page is remapped later | ||
| 712 | */ | ||
| 713 | get_anon_vma(anon_vma); | ||
| 714 | page_unlock_anon_vma(anon_vma); | ||
| 715 | } else if (PageSwapCache(page)) { | ||
| 711 | /* | 716 | /* |
| 712 | * We cannot be sure that the anon_vma of an unmapped | 717 | * We cannot be sure that the anon_vma of an unmapped |
| 713 | * swapcache page is safe to use because we don't | 718 | * swapcache page is safe to use because we don't |
| @@ -722,13 +727,7 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
| 722 | */ | 727 | */ |
| 723 | remap_swapcache = 0; | 728 | remap_swapcache = 0; |
| 724 | } else { | 729 | } else { |
| 725 | /* | 730 | goto uncharge; |
| 726 | * Take a reference count on the anon_vma if the | ||
| 727 | * page is mapped so that it is guaranteed to | ||
| 728 | * exist when the page is remapped later | ||
| 729 | */ | ||
| 730 | anon_vma = page_anon_vma(page); | ||
| 731 | get_anon_vma(anon_vma); | ||
| 732 | } | 731 | } |
| 733 | } | 732 | } |
| 734 | 733 | ||
| @@ -745,16 +744,10 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
| 745 | * free the metadata, so the page can be freed. | 744 | * free the metadata, so the page can be freed. |
| 746 | */ | 745 | */ |
| 747 | if (!page->mapping) { | 746 | if (!page->mapping) { |
| 748 | if (!PageAnon(page) && page_has_private(page)) { | 747 | VM_BUG_ON(PageAnon(page)); |
| 749 | /* | 748 | if (page_has_private(page)) { |
| 750 | * Go direct to try_to_free_buffers() here because | ||
| 751 | * a) that's what try_to_release_page() would do anyway | ||
| 752 | * b) we may be under rcu_read_lock() here, so we can't | ||
| 753 | * use GFP_KERNEL which is what try_to_release_page() | ||
| 754 | * needs to be effective. | ||
| 755 | */ | ||
| 756 | try_to_free_buffers(page); | 749 | try_to_free_buffers(page); |
| 757 | goto rcu_unlock; | 750 | goto uncharge; |
| 758 | } | 751 | } |
| 759 | goto skip_unmap; | 752 | goto skip_unmap; |
| 760 | } | 753 | } |
| @@ -768,14 +761,11 @@ skip_unmap: | |||
| 768 | 761 | ||
| 769 | if (rc && remap_swapcache) | 762 | if (rc && remap_swapcache) |
| 770 | remove_migration_ptes(page, page); | 763 | remove_migration_ptes(page, page); |
| 771 | rcu_unlock: | ||
| 772 | 764 | ||
| 773 | /* Drop an anon_vma reference if we took one */ | 765 | /* Drop an anon_vma reference if we took one */ |
| 774 | if (anon_vma) | 766 | if (anon_vma) |
| 775 | drop_anon_vma(anon_vma); | 767 | drop_anon_vma(anon_vma); |
| 776 | 768 | ||
| 777 | if (rcu_locked) | ||
| 778 | rcu_read_unlock(); | ||
| 779 | uncharge: | 769 | uncharge: |
| 780 | if (!charge) | 770 | if (!charge) |
| 781 | mem_cgroup_end_migration(mem, page, newpage); | 771 | mem_cgroup_end_migration(mem, page, newpage); |
