]> git.ipfire.org Git - people/ms/linux.git/blobdiff - mm/migrate_device.c
Merge tag 'mm-hotfixes-stable-2022-09-26' of git://git.kernel.org/pub/scm/linux/kerne...
[people/ms/linux.git] / mm / migrate_device.c
index 27fb37d65476c24a3103a6c3cf830f4982255c7d..dbf6c7a7a7c9c06f484b0b069167142f6601975f 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/export.h>
 #include <linux/memremap.h>
 #include <linux/migrate.h>
+#include <linux/mm.h>
 #include <linux/mm_inline.h>
 #include <linux/mmu_notifier.h>
 #include <linux/oom.h>
@@ -193,10 +194,10 @@ again:
                        bool anon_exclusive;
                        pte_t swp_pte;
 
+                       flush_cache_page(vma, addr, pte_pfn(*ptep));
                        anon_exclusive = PageAnon(page) && PageAnonExclusive(page);
                        if (anon_exclusive) {
-                               flush_cache_page(vma, addr, pte_pfn(*ptep));
-                               ptep_clear_flush(vma, addr, ptep);
+                               pte = ptep_clear_flush(vma, addr, ptep);
 
                                if (page_try_share_anon_rmap(page)) {
                                        set_pte_at(mm, addr, ptep, pte);
@@ -206,11 +207,15 @@ again:
                                        goto next;
                                }
                        } else {
-                               ptep_get_and_clear(mm, addr, ptep);
+                               pte = ptep_get_and_clear(mm, addr, ptep);
                        }
 
                        migrate->cpages++;
 
+                       /* Set the dirty flag on the folio now the pte is gone. */
+                       if (pte_dirty(pte))
+                               folio_mark_dirty(page_folio(page));
+
                        /* Setup special migration page table entry */
                        if (mpfn & MIGRATE_PFN_WRITE)
                                entry = make_writable_migration_entry(
@@ -254,13 +259,14 @@ next:
                migrate->dst[migrate->npages] = 0;
                migrate->src[migrate->npages++] = mpfn;
        }
-       arch_leave_lazy_mmu_mode();
-       pte_unmap_unlock(ptep - 1, ptl);
 
        /* Only flush the TLB if we actually modified any entries */
        if (unmapped)
                flush_tlb_range(walk->vma, start, end);
 
+       arch_leave_lazy_mmu_mode();
+       pte_unmap_unlock(ptep - 1, ptl);
+
        return 0;
 }