Commit 4983da07f1e2e8dc81cb9d640fbf35b899cdbdf2
Committed by
Linus Torvalds
1 parent
e843e280cb
Exists in
master
and in
4 other branches
[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
fs/buffer.c
| ... | ... | @@ -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 { |
mm/vmscan.c
| ... | ... | @@ -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 |