diff options
Diffstat (limited to 'mm/rmap.c')
| -rw-r--r-- | mm/rmap.c | 51 |
1 files changed, 42 insertions, 9 deletions
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <linux/init.h> | 52 | #include <linux/init.h> |
| 53 | #include <linux/rmap.h> | 53 | #include <linux/rmap.h> |
| 54 | #include <linux/rcupdate.h> | 54 | #include <linux/rcupdate.h> |
| 55 | #include <linux/module.h> | ||
| 55 | 56 | ||
| 56 | #include <asm/tlbflush.h> | 57 | #include <asm/tlbflush.h> |
| 57 | 58 | ||
| @@ -205,6 +206,36 @@ out: | |||
| 205 | return anon_vma; | 206 | return anon_vma; |
| 206 | } | 207 | } |
| 207 | 208 | ||
| 209 | #ifdef CONFIG_MIGRATION | ||
| 210 | /* | ||
| 211 | * Remove an anonymous page from swap replacing the swap pte's | ||
| 212 | * through real pte's pointing to valid pages and then releasing | ||
| 213 | * the page from the swap cache. | ||
| 214 | * | ||
| 215 | * Must hold page lock on page. | ||
| 216 | */ | ||
| 217 | void remove_from_swap(struct page *page) | ||
| 218 | { | ||
| 219 | struct anon_vma *anon_vma; | ||
| 220 | struct vm_area_struct *vma; | ||
| 221 | |||
| 222 | if (!PageAnon(page) || !PageSwapCache(page)) | ||
| 223 | return; | ||
| 224 | |||
| 225 | anon_vma = page_lock_anon_vma(page); | ||
| 226 | if (!anon_vma) | ||
| 227 | return; | ||
| 228 | |||
| 229 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) | ||
| 230 | remove_vma_swap(vma, page); | ||
| 231 | |||
| 232 | spin_unlock(&anon_vma->lock); | ||
| 233 | |||
| 234 | delete_from_swap_cache(page); | ||
| 235 | } | ||
| 236 | EXPORT_SYMBOL(remove_from_swap); | ||
| 237 | #endif | ||
| 238 | |||
| 208 | /* | 239 | /* |
| 209 | * At what user virtual address is page expected in vma? | 240 | * At what user virtual address is page expected in vma? |
| 210 | */ | 241 | */ |
| @@ -541,7 +572,8 @@ void page_remove_rmap(struct page *page) | |||
| 541 | * Subfunctions of try_to_unmap: try_to_unmap_one called | 572 | * Subfunctions of try_to_unmap: try_to_unmap_one called |
| 542 | * repeatedly from either try_to_unmap_anon or try_to_unmap_file. | 573 | * repeatedly from either try_to_unmap_anon or try_to_unmap_file. |
| 543 | */ | 574 | */ |
| 544 | static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma) | 575 | static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, |
| 576 | int ignore_refs) | ||
| 545 | { | 577 | { |
| 546 | struct mm_struct *mm = vma->vm_mm; | 578 | struct mm_struct *mm = vma->vm_mm; |
| 547 | unsigned long address; | 579 | unsigned long address; |
| @@ -564,7 +596,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma) | |||
| 564 | * skipped over this mm) then we should reactivate it. | 596 | * skipped over this mm) then we should reactivate it. |
| 565 | */ | 597 | */ |
| 566 | if ((vma->vm_flags & VM_LOCKED) || | 598 | if ((vma->vm_flags & VM_LOCKED) || |
| 567 | ptep_clear_flush_young(vma, address, pte)) { | 599 | (ptep_clear_flush_young(vma, address, pte) |
| 600 | && !ignore_refs)) { | ||
| 568 | ret = SWAP_FAIL; | 601 | ret = SWAP_FAIL; |
| 569 | goto out_unmap; | 602 | goto out_unmap; |
| 570 | } | 603 | } |
| @@ -698,7 +731,7 @@ static void try_to_unmap_cluster(unsigned long cursor, | |||
| 698 | pte_unmap_unlock(pte - 1, ptl); | 731 | pte_unmap_unlock(pte - 1, ptl); |
| 699 | } | 732 | } |
| 700 | 733 | ||
| 701 | static int try_to_unmap_anon(struct page *page) | 734 | static int try_to_unmap_anon(struct page *page, int ignore_refs) |
| 702 | { | 735 | { |
| 703 | struct anon_vma *anon_vma; | 736 | struct anon_vma *anon_vma; |
| 704 | struct vm_area_struct *vma; | 737 | struct vm_area_struct *vma; |
| @@ -709,7 +742,7 @@ static int try_to_unmap_anon(struct page *page) | |||
| 709 | return ret; | 742 | return ret; |
| 710 | 743 | ||
| 711 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { | 744 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { |
| 712 | ret = try_to_unmap_one(page, vma); | 745 | ret = try_to_unmap_one(page, vma, ignore_refs); |
| 713 | if (ret == SWAP_FAIL || !page_mapped(page)) | 746 | if (ret == SWAP_FAIL || !page_mapped(page)) |
| 714 | break; | 747 | break; |
| 715 | } | 748 | } |
| @@ -726,7 +759,7 @@ static int try_to_unmap_anon(struct page *page) | |||
| 726 | * | 759 | * |
| 727 | * This function is only called from try_to_unmap for object-based pages. | 760 | * This function is only called from try_to_unmap for object-based pages. |
| 728 | */ | 761 | */ |
| 729 | static int try_to_unmap_file(struct page *page) | 762 | static int try_to_unmap_file(struct page *page, int ignore_refs) |
| 730 | { | 763 | { |
| 731 | struct address_space *mapping = page->mapping; | 764 | struct address_space *mapping = page->mapping; |
| 732 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | 765 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); |
| @@ -740,7 +773,7 @@ static int try_to_unmap_file(struct page *page) | |||
| 740 | 773 | ||
| 741 | spin_lock(&mapping->i_mmap_lock); | 774 | spin_lock(&mapping->i_mmap_lock); |
| 742 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 775 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { |
| 743 | ret = try_to_unmap_one(page, vma); | 776 | ret = try_to_unmap_one(page, vma, ignore_refs); |
| 744 | if (ret == SWAP_FAIL || !page_mapped(page)) | 777 | if (ret == SWAP_FAIL || !page_mapped(page)) |
| 745 | goto out; | 778 | goto out; |
| 746 | } | 779 | } |
| @@ -825,16 +858,16 @@ out: | |||
| 825 | * SWAP_AGAIN - we missed a mapping, try again later | 858 | * SWAP_AGAIN - we missed a mapping, try again later |
| 826 | * SWAP_FAIL - the page is unswappable | 859 | * SWAP_FAIL - the page is unswappable |
| 827 | */ | 860 | */ |
| 828 | int try_to_unmap(struct page *page) | 861 | int try_to_unmap(struct page *page, int ignore_refs) |
| 829 | { | 862 | { |
| 830 | int ret; | 863 | int ret; |
| 831 | 864 | ||
| 832 | BUG_ON(!PageLocked(page)); | 865 | BUG_ON(!PageLocked(page)); |
| 833 | 866 | ||
| 834 | if (PageAnon(page)) | 867 | if (PageAnon(page)) |
| 835 | ret = try_to_unmap_anon(page); | 868 | ret = try_to_unmap_anon(page, ignore_refs); |
| 836 | else | 869 | else |
| 837 | ret = try_to_unmap_file(page); | 870 | ret = try_to_unmap_file(page, ignore_refs); |
| 838 | 871 | ||
| 839 | if (!page_mapped(page)) | 872 | if (!page_mapped(page)) |
| 840 | ret = SWAP_SUCCESS; | 873 | ret = SWAP_SUCCESS; |
