提交 4983da07 编写于 作者: C Christoph Lameter 提交者: Linus Torvalds

[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: NChristoph Lameter <clameter@sgi.com>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 e843e280
...@@ -3060,6 +3060,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page) ...@@ -3060,6 +3060,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page)
{ {
struct address_space *mapping = page->mapping; struct address_space *mapping = page->mapping;
struct buffer_head *bh, *head; struct buffer_head *bh, *head;
int rc;
if (!mapping) if (!mapping)
return -EAGAIN; return -EAGAIN;
...@@ -3069,8 +3070,9 @@ int buffer_migrate_page(struct page *newpage, struct page *page) ...@@ -3069,8 +3070,9 @@ int buffer_migrate_page(struct page *newpage, struct page *page)
head = page_buffers(page); head = page_buffers(page);
if (migrate_page_remove_references(newpage, page, 3)) rc = migrate_page_remove_references(newpage, page, 3);
return -EAGAIN; if (rc)
return rc;
bh = head; bh = head;
do { do {
......
...@@ -700,7 +700,7 @@ int migrate_page_remove_references(struct page *newpage, ...@@ -700,7 +700,7 @@ int migrate_page_remove_references(struct page *newpage,
* the page. * the page.
*/ */
if (!mapping || page_mapcount(page) + nr_refs != page_count(page)) if (!mapping || page_mapcount(page) + nr_refs != page_count(page))
return 1; return -EAGAIN;
/* /*
* Establish swap ptes for anonymous pages or destroy pte * Establish swap ptes for anonymous pages or destroy pte
...@@ -721,13 +721,15 @@ int migrate_page_remove_references(struct page *newpage, ...@@ -721,13 +721,15 @@ int migrate_page_remove_references(struct page *newpage,
* If the page was not migrated then the PageSwapCache bit * If the page was not migrated then the PageSwapCache bit
* is still set and the operation may continue. * is still set and the operation may continue.
*/ */
try_to_unmap(page, 1); if (try_to_unmap(page, 1) == SWAP_FAIL)
/* A vma has VM_LOCKED set -> Permanent failure */
return -EPERM;
/* /*
* Give up if we were unable to remove all mappings. * Give up if we were unable to remove all mappings.
*/ */
if (page_mapcount(page)) if (page_mapcount(page))
return 1; return -EAGAIN;
write_lock_irq(&mapping->tree_lock); write_lock_irq(&mapping->tree_lock);
...@@ -738,7 +740,7 @@ int migrate_page_remove_references(struct page *newpage, ...@@ -738,7 +740,7 @@ int migrate_page_remove_references(struct page *newpage,
if (!page_mapping(page) || page_count(page) != nr_refs || if (!page_mapping(page) || page_count(page) != nr_refs ||
*radix_pointer != page) { *radix_pointer != page) {
write_unlock_irq(&mapping->tree_lock); write_unlock_irq(&mapping->tree_lock);
return 1; return -EAGAIN;
} }
/* /*
...@@ -813,10 +815,14 @@ EXPORT_SYMBOL(migrate_page_copy); ...@@ -813,10 +815,14 @@ EXPORT_SYMBOL(migrate_page_copy);
*/ */
int migrate_page(struct page *newpage, struct page *page) int migrate_page(struct page *newpage, struct page *page)
{ {
int rc;
BUG_ON(PageWriteback(page)); /* Writeback must be complete */ BUG_ON(PageWriteback(page)); /* Writeback must be complete */
if (migrate_page_remove_references(newpage, page, 2)) rc = migrate_page_remove_references(newpage, page, 2);
return -EAGAIN;
if (rc)
return rc;
migrate_page_copy(newpage, page); migrate_page_copy(newpage, page);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册