|
@@ -168,19 +168,19 @@ retry:
|
|
|
/*
|
|
|
* Remove references for a page and establish the new page with the correct
|
|
|
* basic settings to be able to stop accesses to the page.
|
|
|
+ *
|
|
|
+ * The number of remaining references must be:
|
|
|
+ * 1 for anonymous pages without a mapping
|
|
|
+ * 2 for pages with a mapping
|
|
|
+ * 3 for pages with a mapping and PagePrivate set.
|
|
|
*/
|
|
|
static int migrate_page_remove_references(struct page *newpage,
|
|
|
- struct page *page, int nr_refs)
|
|
|
+ struct page *page)
|
|
|
{
|
|
|
struct address_space *mapping = page_mapping(page);
|
|
|
struct page **radix_pointer;
|
|
|
|
|
|
- /*
|
|
|
- * Avoid doing any of the following work if the page count
|
|
|
- * indicates that the page is in use or truncate has removed
|
|
|
- * the page.
|
|
|
- */
|
|
|
- if (!mapping || page_mapcount(page) + nr_refs != page_count(page))
|
|
|
+ if (!mapping)
|
|
|
return -EAGAIN;
|
|
|
|
|
|
/*
|
|
@@ -218,7 +218,8 @@ static int migrate_page_remove_references(struct page *newpage,
|
|
|
&mapping->page_tree,
|
|
|
page_index(page));
|
|
|
|
|
|
- if (!page_mapping(page) || page_count(page) != nr_refs ||
|
|
|
+ if (!page_mapping(page) ||
|
|
|
+ page_count(page) != 2 + !!PagePrivate(page) ||
|
|
|
*radix_pointer != page) {
|
|
|
write_unlock_irq(&mapping->tree_lock);
|
|
|
return -EAGAIN;
|
|
@@ -309,7 +310,7 @@ int migrate_page(struct page *newpage, struct page *page)
|
|
|
|
|
|
BUG_ON(PageWriteback(page)); /* Writeback must be complete */
|
|
|
|
|
|
- rc = migrate_page_remove_references(newpage, page, 2);
|
|
|
+ rc = migrate_page_remove_references(newpage, page);
|
|
|
|
|
|
if (rc)
|
|
|
return rc;
|
|
@@ -348,7 +349,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page)
|
|
|
|
|
|
head = page_buffers(page);
|
|
|
|
|
|
- rc = migrate_page_remove_references(newpage, page, 3);
|
|
|
+ rc = migrate_page_remove_references(newpage, page);
|
|
|
|
|
|
if (rc)
|
|
|
return rc;
|