aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/swap.h3
-rw-r--r--mm/mempolicy.c27
-rw-r--r--mm/vmscan.c17
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
179extern int isolate_lru_page(struct page *p); 179extern int isolate_lru_page(struct page *p);
180extern int putback_lru_pages(struct list_head *l); 180extern int putback_lru_pages(struct list_head *l);
181extern int migrate_pages(struct list_head *l, struct list_head *t); 181extern 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
432static 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
432long do_mbind(unsigned long start, unsigned long len, 445long 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 */
673int migrate_pages(struct list_head *l, struct list_head *t) 673int 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)
686redo: 686redo:
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 }
737retry_later: 739retry_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