[PATCH 1/2] mm/memory: factor out anon reuse logic into wp_try_reuse_anon_page()
From: David Hildenbrand (Arm)
Date: Thu Sep 24 2026 - 13:43:15 EST
Let's move the core logic from do_wp_page() into
wp_try_reuse_anon_page() to prepare for further changes.
No functional change intended.
Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
---
mm/memory.c | 45 +++++++++++++++++++++++++++++----------------
1 file changed, 29 insertions(+), 16 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index 338fce99e7119..67fcf67bc64fd 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4414,6 +4414,34 @@ static bool wp_can_reuse_anon_folio(struct folio *folio,
return true;
}
+static bool wp_try_reuse_anon_page(struct vm_fault *vmf, struct folio *folio)
+ __cond_releases(true, vmf->ptl)
+{
+ const bool unshare = vmf->flags & FAULT_FLAG_UNSHARE;
+
+ VM_WARN_ON_ONCE(!folio_test_anon(folio));
+
+ /*
+ * Private mapping: create an exclusive anonymous page copy if reuse
+ * is impossible. We might miss VM_WRITE for FOLL_FORCE handling.
+ *
+ * If we encounter a page that is marked exclusive, we must reuse
+ * the page without further checks.
+ */
+ if (!PageAnonExclusive(vmf->page)) {
+ if (!wp_can_reuse_anon_folio(folio, vmf->vma))
+ return false;
+ SetPageAnonExclusive(vmf->page);
+ }
+
+ if (unlikely(unshare)) {
+ pte_unmap_unlock(vmf->pte, vmf->ptl);
+ return true;
+ }
+ wp_page_reuse(vmf, folio);
+ return true;
+}
+
/*
* This routine handles present pages, when
* * users try to write to a shared page (FAULT_FLAG_WRITE)
@@ -4499,24 +4527,9 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
return wp_page_shared(vmf, folio);
}
- /*
- * Private mapping: create an exclusive anonymous page copy if reuse
- * is impossible. We might miss VM_WRITE for FOLL_FORCE handling.
- *
- * If we encounter a page that is marked exclusive, we must reuse
- * the page without further checks.
- */
if (folio && folio_test_anon(folio) &&
- (PageAnonExclusive(vmf->page) || wp_can_reuse_anon_folio(folio, vma))) {
- if (!PageAnonExclusive(vmf->page))
- SetPageAnonExclusive(vmf->page);
- if (unlikely(unshare)) {
- pte_unmap_unlock(vmf->pte, vmf->ptl);
- return 0;
- }
- wp_page_reuse(vmf, folio);
+ wp_try_reuse_anon_page(vmf, folio))
return 0;
- }
/*
* Ok, we need to copy. Oh, well..
*/
--
2.43.0
And the maybe go into this direction, where we really only try to
batch exactly once, and include in that patch out PTE of interest. IOW, optimize
for the common case and also take care of unsharing.
Some things I am not sure about
* Hardcoding WP_REUSE_MAX_NR_PTES, likely should be determine differently.
* Marking all 16 PTEs young+dirty. It's somewhat the same thing as we do in
map_anon_folio_pte_pf(). On arm64 it's already fuzzy with cont-pte. With
transparent coalescing we'd actually allow it directly. So it does feel like the right thing.
I also wonder whether some part of the function could be factored out as helpers for
other code to use in the future. I also suspect that there are more cleanups to be had.
Long story short, needs more work, but I am out of time.
Entirely untested: