diff options
-rw-r--r-- | include/linux/swap.h | 3 | ||||
-rw-r--r-- | mm/mempolicy.c | 27 | ||||
-rw-r--r-- | mm/vmscan.c | 17 |
3 files changed, 32 insertions, 15 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h index eb591eaad1b7..389d1c382e20 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -178,7 +178,8 @@ extern int vm_swappiness; | |||
178 | #ifdef CONFIG_MIGRATION | 178 | #ifdef CONFIG_MIGRATION |
179 | extern int isolate_lru_page(struct page *p); | 179 | extern int isolate_lru_page(struct page *p); |
180 | extern int putback_lru_pages(struct list_head *l); | 180 | extern int putback_lru_pages(struct list_head *l); |
181 | extern int migrate_pages(struct list_head *l, struct list_head *t); | 181 | extern int migrate_pages(struct list_head *l, struct list_head *t, |
182 | struct list_head *moved, struct list_head *failed); | ||
182 | #endif | 183 | #endif |
183 | 184 | ||
184 | #ifdef CONFIG_MMU | 185 | #ifdef CONFIG_MMU |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 20d5ad39fa41..30bdafba52d8 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -429,6 +429,19 @@ static int contextualize_policy(int mode, nodemask_t *nodes) | |||
429 | return mpol_check_policy(mode, nodes); | 429 | return mpol_check_policy(mode, nodes); |
430 | } | 430 | } |
431 | 431 | ||
432 | static int swap_pages(struct list_head *pagelist) | ||
433 | { | ||
434 | LIST_HEAD(moved); | ||
435 | LIST_HEAD(failed); | ||
436 | int n; | ||
437 | |||
438 | n = migrate_pages(pagelist, NULL, &moved, &failed); | ||
439 | putback_lru_pages(&failed); | ||
440 | putback_lru_pages(&moved); | ||
441 | |||
442 | return n; | ||
443 | } | ||
444 | |||
432 | long do_mbind(unsigned long start, unsigned long len, | 445 | long do_mbind(unsigned long start, unsigned long len, |
433 | unsigned long mode, nodemask_t *nmask, unsigned long flags) | 446 | unsigned long mode, nodemask_t *nmask, unsigned long flags) |
434 | { | 447 | { |
@@ -481,10 +494,13 @@ long do_mbind(unsigned long start, unsigned long len, | |||
481 | (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ? &pagelist : NULL); | 494 | (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ? &pagelist : NULL); |
482 | err = PTR_ERR(vma); | 495 | err = PTR_ERR(vma); |
483 | if (!IS_ERR(vma)) { | 496 | if (!IS_ERR(vma)) { |
497 | int nr_failed = 0; | ||
498 | |||
484 | err = mbind_range(vma, start, end, new); | 499 | err = mbind_range(vma, start, end, new); |
485 | if (!list_empty(&pagelist)) | 500 | if (!list_empty(&pagelist)) |
486 | migrate_pages(&pagelist, NULL); | 501 | nr_failed = swap_pages(&pagelist); |
487 | if (!err && !list_empty(&pagelist) && (flags & MPOL_MF_STRICT)) | 502 | |
503 | if (!err && nr_failed && (flags & MPOL_MF_STRICT)) | ||
488 | err = -EIO; | 504 | err = -EIO; |
489 | } | 505 | } |
490 | if (!list_empty(&pagelist)) | 506 | if (!list_empty(&pagelist)) |
@@ -635,11 +651,12 @@ int do_migrate_pages(struct mm_struct *mm, | |||
635 | down_read(&mm->mmap_sem); | 651 | down_read(&mm->mmap_sem); |
636 | check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nodes, | 652 | check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nodes, |
637 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); | 653 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); |
654 | |||
638 | if (!list_empty(&pagelist)) { | 655 | if (!list_empty(&pagelist)) { |
639 | migrate_pages(&pagelist, NULL); | 656 | count = swap_pages(&pagelist); |
640 | if (!list_empty(&pagelist)) | 657 | putback_lru_pages(&pagelist); |
641 | count = putback_lru_pages(&pagelist); | ||
642 | } | 658 | } |
659 | |||
643 | up_read(&mm->mmap_sem); | 660 | up_read(&mm->mmap_sem); |
644 | return count; | 661 | return count; |
645 | } | 662 | } |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 73ba4046ed27..5eecb514ccea 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -670,10 +670,10 @@ retry: | |||
670 | * list. The direct migration patchset | 670 | * list. The direct migration patchset |
671 | * extends this function to avoid the use of swap. | 671 | * extends this function to avoid the use of swap. |
672 | */ | 672 | */ |
673 | int migrate_pages(struct list_head *l, struct list_head *t) | 673 | int migrate_pages(struct list_head *from, struct list_head *to, |
674 | struct list_head *moved, struct list_head *failed) | ||
674 | { | 675 | { |
675 | int retry; | 676 | int retry; |
676 | LIST_HEAD(failed); | ||
677 | int nr_failed = 0; | 677 | int nr_failed = 0; |
678 | int pass = 0; | 678 | int pass = 0; |
679 | struct page *page; | 679 | struct page *page; |
@@ -686,12 +686,12 @@ int migrate_pages(struct list_head *l, struct list_head *t) | |||
686 | redo: | 686 | redo: |
687 | retry = 0; | 687 | retry = 0; |
688 | 688 | ||
689 | list_for_each_entry_safe(page, page2, l, lru) { | 689 | list_for_each_entry_safe(page, page2, from, lru) { |
690 | cond_resched(); | 690 | cond_resched(); |
691 | 691 | ||
692 | if (page_count(page) == 1) { | 692 | if (page_count(page) == 1) { |
693 | /* page was freed from under us. So we are done. */ | 693 | /* page was freed from under us. So we are done. */ |
694 | move_to_lru(page); | 694 | list_move(&page->lru, moved); |
695 | continue; | 695 | continue; |
696 | } | 696 | } |
697 | /* | 697 | /* |
@@ -722,7 +722,7 @@ redo: | |||
722 | if (PageAnon(page) && !PageSwapCache(page)) { | 722 | if (PageAnon(page) && !PageSwapCache(page)) { |
723 | if (!add_to_swap(page, GFP_KERNEL)) { | 723 | if (!add_to_swap(page, GFP_KERNEL)) { |
724 | unlock_page(page); | 724 | unlock_page(page); |
725 | list_move(&page->lru, &failed); | 725 | list_move(&page->lru, failed); |
726 | nr_failed++; | 726 | nr_failed++; |
727 | continue; | 727 | continue; |
728 | } | 728 | } |
@@ -732,8 +732,10 @@ redo: | |||
732 | * Page is properly locked and writeback is complete. | 732 | * Page is properly locked and writeback is complete. |
733 | * Try to migrate the page. | 733 | * Try to migrate the page. |
734 | */ | 734 | */ |
735 | if (!swap_page(page)) | 735 | if (!swap_page(page)) { |
736 | list_move(&page->lru, moved); | ||
736 | continue; | 737 | continue; |
738 | } | ||
737 | retry_later: | 739 | retry_later: |
738 | retry++; | 740 | retry++; |
739 | } | 741 | } |
@@ -743,9 +745,6 @@ retry_later: | |||
743 | if (!swapwrite) | 745 | if (!swapwrite) |
744 | current->flags &= ~PF_SWAPWRITE; | 746 | current->flags &= ~PF_SWAPWRITE; |
745 | 747 | ||
746 | if (!list_empty(&failed)) | ||
747 | list_splice(&failed, l); | ||
748 | |||
749 | return nr_failed + retry; | 748 | return nr_failed + retry; |
750 | } | 749 | } |
751 | 750 | ||