summaryrefslogtreecommitdiff
path: root/mm/migrate.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/migrate.c')
-rw-r--r--mm/migrate.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index 57559f9295f9..0e80c254d77a 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -943,6 +943,7 @@ static int unmap_and_move(new_page_t get_new_page, free_page_t put_new_page,
int rc = 0;
int *result = NULL;
struct page *newpage = get_new_page(page, private, &result);
+ bool is_lru = !isolated_balloon_page(page);
if (!newpage)
return -ENOMEM;
@@ -975,12 +976,14 @@ out:
/*
* If migration was not successful and there's a freeing callback, use
* it. Otherwise, putback_lru_page() will drop the reference grabbed
- * during isolation.
+ * during isolation. Use the old state of the isolated source page to
+ * determine if we migrated a LRU page. newpage was already unlocked
+ * and possibly modified by its owner - don't rely on the page state.
*/
if (rc != MIGRATEPAGE_SUCCESS && put_new_page) {
ClearPageSwapBacked(newpage);
put_new_page(newpage, private);
- } else if (unlikely(__is_movable_balloon_page(newpage))) {
+ } else if (rc == MIGRATEPAGE_SUCCESS && unlikely(!is_lru)) {
/* drop our reference, page already in the balloon */
put_page(newpage);
} else