Commit aaa994b300a172afafab47938804836b923e5ef7
Committed by
Linus Torvalds
1 parent
e24f0b8f76
Exists in
master
and in
4 other branches
[PATCH] page migration: handle freeing of pages in migrate_pages()
Do not leave pages on the lists passed to migrate_pages(). Seems that we will not need any postprocessing of pages. This will simplify the handling of pages by the callers of migrate_pages(). Signed-off-by: Christoph Lameter <clameter@sgi.com> Cc: Hugh Dickins <hugh@veritas.com> Cc: Jes Sorensen <jes@trained-monkey.org> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Lee Schermerhorn <lee.schermerhorn@hp.com> Cc: Andi Kleen <ak@muc.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 3 changed files with 27 additions and 36 deletions Side-by-side Diff
include/linux/migrate.h
... | ... | @@ -8,8 +8,7 @@ |
8 | 8 | extern int putback_lru_pages(struct list_head *l); |
9 | 9 | extern int migrate_page(struct address_space *, |
10 | 10 | struct page *, struct page *); |
11 | -extern int migrate_pages(struct list_head *l, struct list_head *t, | |
12 | - struct list_head *moved, struct list_head *failed); | |
11 | +extern int migrate_pages(struct list_head *l, struct list_head *t); | |
13 | 12 | extern int migrate_pages_to(struct list_head *pagelist, |
14 | 13 | struct vm_area_struct *vma, int dest); |
15 | 14 | extern int fail_migrate_page(struct address_space *, |
... | ... | @@ -22,8 +21,8 @@ |
22 | 21 | static inline int isolate_lru_page(struct page *p, struct list_head *list) |
23 | 22 | { return -ENOSYS; } |
24 | 23 | static inline int putback_lru_pages(struct list_head *l) { return 0; } |
25 | -static inline int migrate_pages(struct list_head *l, struct list_head *t, | |
26 | - struct list_head *moved, struct list_head *failed) { return -ENOSYS; } | |
24 | +static inline int migrate_pages(struct list_head *l, struct list_head *t) | |
25 | + { return -ENOSYS; } | |
27 | 26 | |
28 | 27 | static inline int migrate_pages_to(struct list_head *pagelist, |
29 | 28 | struct vm_area_struct *vma, int dest) { return 0; } |
mm/mempolicy.c
... | ... | @@ -603,11 +603,8 @@ |
603 | 603 | check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nmask, |
604 | 604 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); |
605 | 605 | |
606 | - if (!list_empty(&pagelist)) { | |
606 | + if (!list_empty(&pagelist)) | |
607 | 607 | err = migrate_pages_to(&pagelist, NULL, dest); |
608 | - if (!list_empty(&pagelist)) | |
609 | - putback_lru_pages(&pagelist); | |
610 | - } | |
611 | 608 | return err; |
612 | 609 | } |
613 | 610 | |
... | ... | @@ -772,9 +769,6 @@ |
772 | 769 | if (!err && nr_failed && (flags & MPOL_MF_STRICT)) |
773 | 770 | err = -EIO; |
774 | 771 | } |
775 | - | |
776 | - if (!list_empty(&pagelist)) | |
777 | - putback_lru_pages(&pagelist); | |
778 | 772 | |
779 | 773 | up_write(&mm->mmap_sem); |
780 | 774 | mpol_free(new); |
mm/migrate.c
... | ... | @@ -624,6 +624,15 @@ |
624 | 624 | unlock_page(page); |
625 | 625 | ret: |
626 | 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 | 636 | list_del(&newpage->lru); |
628 | 637 | move_to_lru(newpage); |
629 | 638 | } |
630 | 639 | |
631 | 640 | |
... | ... | @@ -640,12 +649,12 @@ |
640 | 649 | * |
641 | 650 | * The function returns after 10 attempts or if no pages |
642 | 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, | |
648 | - struct list_head *moved, struct list_head *failed) | |
657 | +int migrate_pages(struct list_head *from, struct list_head *to) | |
649 | 658 | { |
650 | 659 | int retry = 1; |
651 | 660 | int nr_failed = 0; |
652 | 661 | |
... | ... | @@ -675,11 +684,9 @@ |
675 | 684 | retry++; |
676 | 685 | break; |
677 | 686 | case 0: |
678 | - list_move(&page->lru, moved); | |
679 | 687 | break; |
680 | 688 | default: |
681 | 689 | /* Permanent failure */ |
682 | - list_move(&page->lru, failed); | |
683 | 690 | nr_failed++; |
684 | 691 | break; |
685 | 692 | } |
... | ... | @@ -689,6 +696,7 @@ |
689 | 696 | if (!swapwrite) |
690 | 697 | current->flags &= ~PF_SWAPWRITE; |
691 | 698 | |
699 | + putback_lru_pages(from); | |
692 | 700 | return nr_failed + retry; |
693 | 701 | } |
694 | 702 | |
695 | 703 | |
... | ... | @@ -702,11 +710,10 @@ |
702 | 710 | struct vm_area_struct *vma, int dest) |
703 | 711 | { |
704 | 712 | LIST_HEAD(newlist); |
705 | - LIST_HEAD(moved); | |
706 | - LIST_HEAD(failed); | |
707 | 713 | int err = 0; |
708 | 714 | unsigned long offset = 0; |
709 | 715 | int nr_pages; |
716 | + int nr_failed = 0; | |
710 | 717 | struct page *page; |
711 | 718 | struct list_head *p; |
712 | 719 | |
713 | 720 | |
714 | 721 | |
715 | 722 | |
716 | 723 | |
... | ... | @@ -740,27 +747,18 @@ |
740 | 747 | if (nr_pages > MIGRATE_CHUNK_SIZE) |
741 | 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 ?? */ | |
746 | - | |
747 | - if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist)) | |
748 | - 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); | |
752 | + if (err >= 0) { | |
753 | + nr_failed += err; | |
754 | + if (list_empty(&newlist) && !list_empty(pagelist)) | |
755 | + goto redo; | |
755 | 756 | } |
756 | - list_splice(&failed, pagelist); | |
757 | - if (err < 0) | |
758 | - return err; | |
757 | +out: | |
759 | 758 | |
760 | 759 | /* Calculate number of leftover pages */ |
761 | - nr_pages = 0; | |
762 | 760 | list_for_each(p, pagelist) |
763 | - nr_pages++; | |
764 | - return nr_pages; | |
761 | + nr_failed++; | |
762 | + return nr_failed; | |
765 | 763 | } |