Commit 4983da07f1e2e8dc81cb9d640fbf35b899cdbdf2

Authored by Christoph Lameter
Committed by Linus Torvalds
1 parent e843e280cb

[PATCH] page migration: fail if page is in a vma flagged VM_LOCKED

page migration currently simply retries a couple of times if try_to_unmap()
fails without inspecting the return code.

However, SWAP_FAIL indicates that the page is in a vma that has the
VM_LOCKED flag set (if ignore_refs ==1).  We can check for that return code
and avoid retrying the migration.

migrate_page_remove_references() now needs to return a reason why the
failure occured.  So switch migrate_page_remove_references to use -Exx
style error messages.

Signed-off-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 2 changed files with 16 additions and 8 deletions Side-by-side Diff

... ... @@ -3060,6 +3060,7 @@
3060 3060 {
3061 3061 struct address_space *mapping = page->mapping;
3062 3062 struct buffer_head *bh, *head;
  3063 + int rc;
3063 3064  
3064 3065 if (!mapping)
3065 3066 return -EAGAIN;
... ... @@ -3069,8 +3070,9 @@
3069 3070  
3070 3071 head = page_buffers(page);
3071 3072  
3072   - if (migrate_page_remove_references(newpage, page, 3))
3073   - return -EAGAIN;
  3073 + rc = migrate_page_remove_references(newpage, page, 3);
  3074 + if (rc)
  3075 + return rc;
3074 3076  
3075 3077 bh = head;
3076 3078 do {
... ... @@ -700,7 +700,7 @@
700 700 * the page.
701 701 */
702 702 if (!mapping || page_mapcount(page) + nr_refs != page_count(page))
703   - return 1;
  703 + return -EAGAIN;
704 704  
705 705 /*
706 706 * Establish swap ptes for anonymous pages or destroy pte
707 707  
... ... @@ -721,13 +721,15 @@
721 721 * If the page was not migrated then the PageSwapCache bit
722 722 * is still set and the operation may continue.
723 723 */
724   - try_to_unmap(page, 1);
  724 + if (try_to_unmap(page, 1) == SWAP_FAIL)
  725 + /* A vma has VM_LOCKED set -> Permanent failure */
  726 + return -EPERM;
725 727  
726 728 /*
727 729 * Give up if we were unable to remove all mappings.
728 730 */
729 731 if (page_mapcount(page))
730   - return 1;
  732 + return -EAGAIN;
731 733  
732 734 write_lock_irq(&mapping->tree_lock);
733 735  
... ... @@ -738,7 +740,7 @@
738 740 if (!page_mapping(page) || page_count(page) != nr_refs ||
739 741 *radix_pointer != page) {
740 742 write_unlock_irq(&mapping->tree_lock);
741   - return 1;
  743 + return -EAGAIN;
742 744 }
743 745  
744 746 /*
745 747  
... ... @@ -813,10 +815,14 @@
813 815 */
814 816 int migrate_page(struct page *newpage, struct page *page)
815 817 {
  818 + int rc;
  819 +
816 820 BUG_ON(PageWriteback(page)); /* Writeback must be complete */
817 821  
818   - if (migrate_page_remove_references(newpage, page, 2))
819   - return -EAGAIN;
  822 + rc = migrate_page_remove_references(newpage, page, 2);
  823 +
  824 + if (rc)
  825 + return rc;
820 826  
821 827 migrate_page_copy(newpage, page);
822 828