[PATCH v2 2/2] mm: Extract non-swap page handling to do_non_swap_page()
From: Hongfu Li
Date: Wed Jul 22 2026 - 23:10:31 EST
From: Hongfu Li <lihongfu@xxxxxxxxxx>
Factor non-swap entry logic out of bloated do_swap_page() to simplify
the main swap fault flow and improve readability.
The new do_non_swap_page() handles migration, device private/exclusive,
hwpoison, marker and bad PTE entries.
Signed-off-by: Hongfu Li <lihongfu@xxxxxxxxxx>
---
mm/memory.c | 120 ++++++++++++++++++++++++++++++----------------------
1 file changed, 69 insertions(+), 51 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index ae521baa8c84..50d8e92aef91 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4815,6 +4815,74 @@ static void check_swap_exclusive(struct folio *folio, swp_entry_t entry,
} while (--nr_pages);
}
+static vm_fault_t do_non_swap_page(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct folio *folio;
+ softleaf_t entry;
+ vm_fault_t ret = 0;
+
+ entry = softleaf_from_pte(vmf->orig_pte);
+ if (softleaf_is_migration(entry)) {
+ migration_entry_wait(vma->vm_mm, vmf->pmd,
+ vmf->address);
+ } else if (softleaf_is_device_exclusive(entry)) {
+ vmf->page = softleaf_to_page(entry);
+ ret = remove_device_exclusive_entry(vmf);
+ } else if (softleaf_is_device_private(entry)) {
+
+ if (vmf->flags & FAULT_FLAG_VMA_LOCK) {
+ /*
+ * migrate_to_ram is not yet ready to operate
+ * under VMA lock.
+ */
+ vma_end_read(vma);
+ return VM_FAULT_RETRY;
+ }
+
+ vmf->page = softleaf_to_page(entry);
+ vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd,
+ vmf->address, &vmf->ptl);
+ if (unlikely(!vmf->pte ||
+ !pte_same(ptep_get(vmf->pte),
+ vmf->orig_pte)))
+ goto unlock;
+
+ /*
+ * Get a folio reference while we know the folio can't be
+ * freed.
+ */
+ folio = page_folio(vmf->page);
+ if (folio_trylock(folio)) {
+ struct dev_pagemap *pgmap;
+
+ folio_get(folio);
+ pte_unmap_unlock(vmf->pte, vmf->ptl);
+ pgmap = page_pgmap(vmf->page);
+ ret = pgmap->ops->migrate_to_ram(vmf);
+ folio_unlock(folio);
+ folio_put(folio);
+ } else {
+ pte_unmap(vmf->pte);
+ softleaf_entry_wait_on_locked(entry, vmf->ptl);
+ }
+ } else if (softleaf_is_hwpoison(entry)) {
+ ret = VM_FAULT_HWPOISON;
+ } else if (softleaf_is_marker(entry)) {
+ ret = handle_pte_marker(vmf);
+ } else {
+ print_bad_pte(vma, vmf->address, vmf->orig_pte, NULL);
+ ret = VM_FAULT_SIGBUS;
+ }
+
+ return ret;
+
+unlock:
+ if (vmf->pte)
+ pte_unmap_unlock(vmf->pte, vmf->ptl);
+ return ret;
+}
+
/*
* We enter with either the VMA lock or the mmap_lock held (see
* FAULT_FLAG_VMA_LOCK), and pte mapped but not yet locked.
@@ -4845,57 +4913,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
entry = softleaf_from_pte(vmf->orig_pte);
if (unlikely(!softleaf_is_swap(entry))) {
- if (softleaf_is_migration(entry)) {
- migration_entry_wait(vma->vm_mm, vmf->pmd,
- vmf->address);
- } else if (softleaf_is_device_exclusive(entry)) {
- vmf->page = softleaf_to_page(entry);
- ret = remove_device_exclusive_entry(vmf);
- } else if (softleaf_is_device_private(entry)) {
- if (vmf->flags & FAULT_FLAG_VMA_LOCK) {
- /*
- * migrate_to_ram is not yet ready to operate
- * under VMA lock.
- */
- vma_end_read(vma);
- ret = VM_FAULT_RETRY;
- goto out;
- }
-
- vmf->page = softleaf_to_page(entry);
- vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd,
- vmf->address, &vmf->ptl);
- if (unlikely(!vmf->pte ||
- !pte_same(ptep_get(vmf->pte),
- vmf->orig_pte)))
- goto unlock;
-
- /*
- * Get a folio reference while we know the folio can't be
- * freed.
- */
- folio = page_folio(vmf->page);
- if (folio_trylock(folio)) {
- struct dev_pagemap *pgmap;
-
- folio_get(folio);
- pte_unmap_unlock(vmf->pte, vmf->ptl);
- pgmap = page_pgmap(vmf->page);
- ret = pgmap->ops->migrate_to_ram(vmf);
- folio_unlock(folio);
- folio_put(folio);
- } else {
- pte_unmap(vmf->pte);
- softleaf_entry_wait_on_locked(entry, vmf->ptl);
- }
- } else if (softleaf_is_hwpoison(entry)) {
- ret = VM_FAULT_HWPOISON;
- } else if (softleaf_is_marker(entry)) {
- ret = handle_pte_marker(vmf);
- } else {
- print_bad_pte(vma, vmf->address, vmf->orig_pte, NULL);
- ret = VM_FAULT_SIGBUS;
- }
+ ret = do_non_swap_page(vmf);
goto out;
}
--
2.54.0