diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/mempolicy.c | 8 | ||||
-rw-r--r-- | mm/migrate.c | 48 |
2 files changed, 24 insertions, 32 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 8778f58880c4..244f3f130e4a 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -603,11 +603,8 @@ int migrate_to_node(struct mm_struct *mm, int source, int dest, int flags) | |||
603 | check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nmask, | 603 | check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nmask, |
604 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); | 604 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); |
605 | 605 | ||
606 | if (!list_empty(&pagelist)) { | 606 | if (!list_empty(&pagelist)) |
607 | err = migrate_pages_to(&pagelist, NULL, dest); | 607 | err = migrate_pages_to(&pagelist, NULL, dest); |
608 | if (!list_empty(&pagelist)) | ||
609 | putback_lru_pages(&pagelist); | ||
610 | } | ||
611 | return err; | 608 | return err; |
612 | } | 609 | } |
613 | 610 | ||
@@ -773,9 +770,6 @@ long do_mbind(unsigned long start, unsigned long len, | |||
773 | err = -EIO; | 770 | err = -EIO; |
774 | } | 771 | } |
775 | 772 | ||
776 | if (!list_empty(&pagelist)) | ||
777 | putback_lru_pages(&pagelist); | ||
778 | |||
779 | up_write(&mm->mmap_sem); | 773 | up_write(&mm->mmap_sem); |
780 | mpol_free(new); | 774 | mpol_free(new); |
781 | return err; | 775 | return err; |
diff --git a/mm/migrate.c b/mm/migrate.c index 09038163bfec..d3a1810a4c9f 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -624,6 +624,15 @@ unlock: | |||
624 | unlock_page(page); | 624 | unlock_page(page); |
625 | ret: | 625 | ret: |
626 | if (rc != -EAGAIN) { | 626 | if (rc != -EAGAIN) { |
627 | /* | ||
628 | * A page that has been migrated has all references | ||
629 | * removed and will be freed. A page that has not been | ||
630 | * migrated will have kepts its references and be | ||
631 | * restored. | ||
632 | */ | ||
633 | list_del(&page->lru); | ||
634 | move_to_lru(page); | ||
635 | |||
627 | list_del(&newpage->lru); | 636 | list_del(&newpage->lru); |
628 | move_to_lru(newpage); | 637 | move_to_lru(newpage); |
629 | } | 638 | } |
@@ -640,12 +649,12 @@ ret: | |||
640 | * | 649 | * |
641 | * The function returns after 10 attempts or if no pages | 650 | * The function returns after 10 attempts or if no pages |
642 | * are movable anymore because to has become empty | 651 | * are movable anymore because to has become empty |
643 | * or no retryable pages exist anymore. | 652 | * or no retryable pages exist anymore. All pages will be |
653 | * retruned to the LRU or freed. | ||
644 | * | 654 | * |
645 | * Return: Number of pages not migrated when "to" ran empty. | 655 | * Return: Number of pages not migrated. |
646 | */ | 656 | */ |
647 | int migrate_pages(struct list_head *from, struct list_head *to, | 657 | int migrate_pages(struct list_head *from, struct list_head *to) |
648 | struct list_head *moved, struct list_head *failed) | ||
649 | { | 658 | { |
650 | int retry = 1; | 659 | int retry = 1; |
651 | int nr_failed = 0; | 660 | int nr_failed = 0; |
@@ -675,11 +684,9 @@ int migrate_pages(struct list_head *from, struct list_head *to, | |||
675 | retry++; | 684 | retry++; |
676 | break; | 685 | break; |
677 | case 0: | 686 | case 0: |
678 | list_move(&page->lru, moved); | ||
679 | break; | 687 | break; |
680 | default: | 688 | default: |
681 | /* Permanent failure */ | 689 | /* Permanent failure */ |
682 | list_move(&page->lru, failed); | ||
683 | nr_failed++; | 690 | nr_failed++; |
684 | break; | 691 | break; |
685 | } | 692 | } |
@@ -689,6 +696,7 @@ int migrate_pages(struct list_head *from, struct list_head *to, | |||
689 | if (!swapwrite) | 696 | if (!swapwrite) |
690 | current->flags &= ~PF_SWAPWRITE; | 697 | current->flags &= ~PF_SWAPWRITE; |
691 | 698 | ||
699 | putback_lru_pages(from); | ||
692 | return nr_failed + retry; | 700 | return nr_failed + retry; |
693 | } | 701 | } |
694 | 702 | ||
@@ -702,11 +710,10 @@ int migrate_pages_to(struct list_head *pagelist, | |||
702 | struct vm_area_struct *vma, int dest) | 710 | struct vm_area_struct *vma, int dest) |
703 | { | 711 | { |
704 | LIST_HEAD(newlist); | 712 | LIST_HEAD(newlist); |
705 | LIST_HEAD(moved); | ||
706 | LIST_HEAD(failed); | ||
707 | int err = 0; | 713 | int err = 0; |
708 | unsigned long offset = 0; | 714 | unsigned long offset = 0; |
709 | int nr_pages; | 715 | int nr_pages; |
716 | int nr_failed = 0; | ||
710 | struct page *page; | 717 | struct page *page; |
711 | struct list_head *p; | 718 | struct list_head *p; |
712 | 719 | ||
@@ -740,26 +747,17 @@ redo: | |||
740 | if (nr_pages > MIGRATE_CHUNK_SIZE) | 747 | if (nr_pages > MIGRATE_CHUNK_SIZE) |
741 | break; | 748 | break; |
742 | } | 749 | } |
743 | err = migrate_pages(pagelist, &newlist, &moved, &failed); | 750 | err = migrate_pages(pagelist, &newlist); |
744 | 751 | ||
745 | putback_lru_pages(&moved); /* Call release pages instead ?? */ | 752 | if (err >= 0) { |
746 | 753 | nr_failed += err; | |
747 | if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist)) | 754 | if (list_empty(&newlist) && !list_empty(pagelist)) |
748 | goto redo; | 755 | goto redo; |
749 | out: | ||
750 | /* Return leftover allocated pages */ | ||
751 | while (!list_empty(&newlist)) { | ||
752 | page = list_entry(newlist.next, struct page, lru); | ||
753 | list_del(&page->lru); | ||
754 | __free_page(page); | ||
755 | } | 756 | } |
756 | list_splice(&failed, pagelist); | 757 | out: |
757 | if (err < 0) | ||
758 | return err; | ||
759 | 758 | ||
760 | /* Calculate number of leftover pages */ | 759 | /* Calculate number of leftover pages */ |
761 | nr_pages = 0; | ||
762 | list_for_each(p, pagelist) | 760 | list_for_each(p, pagelist) |
763 | nr_pages++; | 761 | nr_failed++; |
764 | return nr_pages; | 762 | return nr_failed; |
765 | } | 763 | } |