summaryrefslogtreecommitdiff
path: root/mm/huge_memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r--mm/huge_memory.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index f53bc54dacb3..2c118713f771 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2282,12 +2282,14 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
{
spinlock_t *ptl;
struct mmu_notifier_range range;
+ bool pmd_migration;
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
address & HPAGE_PMD_MASK,
(address & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE);
mmu_notifier_invalidate_range_start(&range);
ptl = pmd_lock(vma->vm_mm, pmd);
+ pmd_migration = is_pmd_migration_entry(*pmd);
/*
* If caller asks to setup a migration entry, we need a folio to check
@@ -2296,13 +2298,12 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
VM_BUG_ON(freeze && !folio);
VM_WARN_ON_ONCE(folio && !folio_test_locked(folio));
- if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd) ||
- is_pmd_migration_entry(*pmd)) {
+ if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd) || pmd_migration) {
/*
- * It's safe to call pmd_page when folio is set because it's
- * guaranteed that pmd is present.
+ * Do not apply pmd_folio() to a migration entry; and folio lock
+ * guarantees that it must be of the wrong folio anyway.
*/
- if (folio && folio != page_folio(pmd_page(*pmd)))
+ if (folio && (pmd_migration || folio != page_folio(pmd_page(*pmd))))
goto out;
__split_huge_pmd_locked(vma, pmd, range.start, freeze);
}