summaryrefslogtreecommitdiff
path: root/mm/migrate_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/migrate_device.c')
-rw-r--r--mm/migrate_device.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index 18d097c38853..762c5cee8fec 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -882,7 +882,7 @@ static int migrate_vma_insert_huge_pmd_page(struct migrate_vma *migrate,
if (flush) {
pte_free(vma->vm_mm, pgtable);
- flush_cache_page(vma, addr, addr + HPAGE_PMD_SIZE);
+ flush_cache_range(vma, addr, addr + HPAGE_PMD_SIZE);
pmdp_invalidate(vma, addr, pmdp);
} else {
pgtable_trans_huge_deposit(vma->vm_mm, pmdp, pgtable);
@@ -1193,6 +1193,13 @@ static void __migrate_device_pages(unsigned long *src_pfns,
MIGRATE_PFN_COMPOUND);
goto next;
}
+
+ /*
+ * reset nr so that only first after-split folio
+ * is processed below
+ */
+ VM_WARN_ON_ONCE(folio_test_large(folio));
+ nr = 1;
} else if ((src_pfns[i] & MIGRATE_PFN_MIGRATE) &&
(dst_pfns[i] & MIGRATE_PFN_COMPOUND) &&
!(src_pfns[i] & MIGRATE_PFN_COMPOUND)) {
@@ -1232,6 +1239,12 @@ static void __migrate_device_pages(unsigned long *src_pfns,
folio = page_folio(migrate_pfn_to_page(src_pfns[i+j]));
newfolio = page_folio(migrate_pfn_to_page(dst_pfns[i+j]));
+ /*
+ * folio_free_swap() removed the folio from the swap
+ * cache. Refresh the saved mapping before migration.
+ */
+ mapping = folio_mapping(folio);
+
r = folio_migrate_mapping(mapping, newfolio, folio, extra_cnt);
if (r)
src_pfns[i+j] &= ~MIGRATE_PFN_MIGRATE;