diff options
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index f1e69c30d203..1f9cf0d073b8 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -554,6 +554,15 @@ static int unuse_mm(struct mm_struct *mm, | |||
554 | return 0; | 554 | return 0; |
555 | } | 555 | } |
556 | 556 | ||
557 | #ifdef CONFIG_MIGRATION | ||
558 | int remove_vma_swap(struct vm_area_struct *vma, struct page *page) | ||
559 | { | ||
560 | swp_entry_t entry = { .val = page_private(page) }; | ||
561 | |||
562 | return unuse_vma(vma, entry, page); | ||
563 | } | ||
564 | #endif | ||
565 | |||
557 | /* | 566 | /* |
558 | * Scan swap_map from current position to next entry still in use. | 567 | * Scan swap_map from current position to next entry still in use. |
559 | * Recycle to start on reaching the end, returning 0 when empty. | 568 | * Recycle to start on reaching the end, returning 0 when empty. |
@@ -646,6 +655,7 @@ static int try_to_unuse(unsigned int type) | |||
646 | */ | 655 | */ |
647 | swap_map = &si->swap_map[i]; | 656 | swap_map = &si->swap_map[i]; |
648 | entry = swp_entry(type, i); | 657 | entry = swp_entry(type, i); |
658 | again: | ||
649 | page = read_swap_cache_async(entry, NULL, 0); | 659 | page = read_swap_cache_async(entry, NULL, 0); |
650 | if (!page) { | 660 | if (!page) { |
651 | /* | 661 | /* |
@@ -680,6 +690,12 @@ static int try_to_unuse(unsigned int type) | |||
680 | wait_on_page_locked(page); | 690 | wait_on_page_locked(page); |
681 | wait_on_page_writeback(page); | 691 | wait_on_page_writeback(page); |
682 | lock_page(page); | 692 | lock_page(page); |
693 | if (!PageSwapCache(page)) { | ||
694 | /* Page migration has occured */ | ||
695 | unlock_page(page); | ||
696 | page_cache_release(page); | ||
697 | goto again; | ||
698 | } | ||
683 | wait_on_page_writeback(page); | 699 | wait_on_page_writeback(page); |
684 | 700 | ||
685 | /* | 701 | /* |