Skip to content

Commit ad7df76

Browse files
apoppletorvalds
authored andcommitted
mm/rmap: fixup copying of soft dirty and uffd ptes
During memory migration a pte is temporarily replaced with a migration swap pte. Some pte bits from the existing mapping such as the soft-dirty and uffd write-protect bits are preserved by copying these to the temporary migration swap pte. However these bits are not stored at the same location for swap and non-swap ptes. Therefore testing these bits requires using the appropriate helper function for the given pte type. Unfortunately several code locations were found where the wrong helper function is being used to test soft_dirty and uffd_wp bits which leads to them getting incorrectly set or cleared during page-migration. Fix these by using the correct tests based on pte type. Fixes: a5430dd ("mm/migrate: support un-addressable ZONE_DEVICE page in migration") Fixes: 8c3328f ("mm/migrate: migrate_vma() unmap page from vma while collecting pages") Fixes: f45ec5f ("userfaultfd: wp: support swap and page migration") Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Peter Xu <peterx@redhat.com> Cc: Jérôme Glisse <jglisse@redhat.com> Cc: John Hubbard <jhubbard@nvidia.com> Cc: Ralph Campbell <rcampbell@nvidia.com> Cc: Alistair Popple <alistair@popple.id.au> Cc: <stable@vger.kernel.org> Link: https://lkml.kernel.org/r/20200825064232.10023-2-alistair@popple.id.au Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent ebdf832 commit ad7df76

2 files changed

Lines changed: 18 additions & 6 deletions

File tree

mm/migrate.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,10 +2427,17 @@ static int migrate_vma_collect_pmd(pmd_t *pmdp,
24272427
entry = make_migration_entry(page, mpfn &
24282428
MIGRATE_PFN_WRITE);
24292429
swp_pte = swp_entry_to_pte(entry);
2430-
if (pte_soft_dirty(pte))
2431-
swp_pte = pte_swp_mksoft_dirty(swp_pte);
2432-
if (pte_uffd_wp(pte))
2433-
swp_pte = pte_swp_mkuffd_wp(swp_pte);
2430+
if (pte_present(pte)) {
2431+
if (pte_soft_dirty(pte))
2432+
swp_pte = pte_swp_mksoft_dirty(swp_pte);
2433+
if (pte_uffd_wp(pte))
2434+
swp_pte = pte_swp_mkuffd_wp(swp_pte);
2435+
} else {
2436+
if (pte_swp_soft_dirty(pte))
2437+
swp_pte = pte_swp_mksoft_dirty(swp_pte);
2438+
if (pte_swp_uffd_wp(pte))
2439+
swp_pte = pte_swp_mkuffd_wp(swp_pte);
2440+
}
24342441
set_pte_at(mm, addr, ptep, swp_pte);
24352442

24362443
/*

mm/rmap.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,9 +1511,14 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
15111511
*/
15121512
entry = make_migration_entry(page, 0);
15131513
swp_pte = swp_entry_to_pte(entry);
1514-
if (pte_soft_dirty(pteval))
1514+
1515+
/*
1516+
* pteval maps a zone device page and is therefore
1517+
* a swap pte.
1518+
*/
1519+
if (pte_swp_soft_dirty(pteval))
15151520
swp_pte = pte_swp_mksoft_dirty(swp_pte);
1516-
if (pte_uffd_wp(pteval))
1521+
if (pte_swp_uffd_wp(pteval))
15171522
swp_pte = pte_swp_mkuffd_wp(swp_pte);
15181523
set_pte_at(mm, pvmw.address, pvmw.pte, swp_pte);
15191524
/*

0 commit comments

Comments
 (0)