|
|
@@ -722,7 +722,7 @@ static int fallback_migrate_page(struct address_space *mapping,
|
|
|
* MIGRATEPAGE_SUCCESS - success
|
|
|
*/
|
|
|
static int move_to_new_page(struct page *newpage, struct page *page,
|
|
|
- int page_was_mapped, enum migrate_mode mode)
|
|
|
+ enum migrate_mode mode)
|
|
|
{
|
|
|
struct address_space *mapping;
|
|
|
int rc;
|
|
|
@@ -755,19 +755,21 @@ static int move_to_new_page(struct page *newpage, struct page *page,
|
|
|
* space which also has its own migratepage callback. This
|
|
|
* is the most common path for page migration.
|
|
|
*/
|
|
|
- rc = mapping->a_ops->migratepage(mapping,
|
|
|
- newpage, page, mode);
|
|
|
+ rc = mapping->a_ops->migratepage(mapping, newpage, page, mode);
|
|
|
else
|
|
|
rc = fallback_migrate_page(mapping, newpage, page, mode);
|
|
|
|
|
|
- if (rc != MIGRATEPAGE_SUCCESS) {
|
|
|
+ /*
|
|
|
+ * When successful, old pagecache page->mapping must be cleared before
|
|
|
+ * page is freed; but stats require that PageAnon be left as PageAnon.
|
|
|
+ */
|
|
|
+ if (rc == MIGRATEPAGE_SUCCESS) {
|
|
|
+ set_page_memcg(page, NULL);
|
|
|
+ if (!PageAnon(page))
|
|
|
+ page->mapping = NULL;
|
|
|
+ } else {
|
|
|
set_page_memcg(newpage, NULL);
|
|
|
newpage->mapping = NULL;
|
|
|
- } else {
|
|
|
- set_page_memcg(page, NULL);
|
|
|
- if (page_was_mapped)
|
|
|
- remove_migration_ptes(page, newpage);
|
|
|
- page->mapping = NULL;
|
|
|
}
|
|
|
return rc;
|
|
|
}
|
|
|
@@ -902,10 +904,11 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
|
|
|
}
|
|
|
|
|
|
if (!page_mapped(page))
|
|
|
- rc = move_to_new_page(newpage, page, page_was_mapped, mode);
|
|
|
+ rc = move_to_new_page(newpage, page, mode);
|
|
|
|
|
|
- if (rc && page_was_mapped)
|
|
|
- remove_migration_ptes(page, page);
|
|
|
+ if (page_was_mapped)
|
|
|
+ remove_migration_ptes(page,
|
|
|
+ rc == MIGRATEPAGE_SUCCESS ? newpage : page);
|
|
|
|
|
|
out_unlock_both:
|
|
|
unlock_page(newpage);
|
|
|
@@ -1066,10 +1069,11 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
|
|
|
}
|
|
|
|
|
|
if (!page_mapped(hpage))
|
|
|
- rc = move_to_new_page(new_hpage, hpage, page_was_mapped, mode);
|
|
|
+ rc = move_to_new_page(new_hpage, hpage, mode);
|
|
|
|
|
|
- if (rc != MIGRATEPAGE_SUCCESS && page_was_mapped)
|
|
|
- remove_migration_ptes(hpage, hpage);
|
|
|
+ if (page_was_mapped)
|
|
|
+ remove_migration_ptes(hpage,
|
|
|
+ rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage);
|
|
|
|
|
|
unlock_page(new_hpage);
|
|
|
|