Commit aaa994b300a172afafab47938804836b923e5ef7

Authored by Christoph Lameter
Committed by Linus Torvalds
1 parent e24f0b8f76

[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; }
... ... @@ -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);
... ... @@ -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 }