[RFC PATCH 01/57] mm: add pte_folio()
From: Kiryl Shutsemau
Date: Sun Aug 16 2026 - 18:46:32 EST
From: "Kiryl Shutsemau (Meta)" <kas@xxxxxxxxxx>
Callers that want the folio behind a present PTE spell it out as
page_folio(pte_page(pte)).
Add pte_folio() as the folio companion to pte_page(), and convert the
callers in fs/proc/task_mmu.c and mm/hugetlb.c.
Preparation for the anonymous collapse engine, which reads the folio
behind a PTE in several places.
Assisted-by: Claude-Code:claude-opus-5
Signed-off-by: Kiryl Shutsemau (Meta) <kas@xxxxxxxxxx>
---
fs/proc/task_mmu.c | 4 ++--
include/linux/mm.h | 14 ++++++++++++++
mm/hugetlb.c | 8 ++++----
3 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 5c54aebe2118..459c779b8141 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1277,7 +1277,7 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,
ptl = huge_pte_lock(hstate_vma(vma), walk->mm, pte);
ptent = huge_ptep_get(walk->mm, addr, pte);
if (pte_present(ptent)) {
- folio = page_folio(pte_page(ptent));
+ folio = pte_folio(ptent);
present = true;
} else {
const softleaf_t entry = softleaf_from_pte(ptent);
@@ -2227,7 +2227,7 @@ static int pagemap_hugetlb_range(pte_t *ptep, unsigned long hmask,
ptl = huge_pte_lock(hstate_vma(vma), walk->mm, ptep);
pte = huge_ptep_get(walk->mm, addr, ptep);
if (pte_present(pte)) {
- struct folio *folio = page_folio(pte_page(pte));
+ struct folio *folio = pte_folio(pte);
if (!folio_test_anon(folio))
flags |= PM_FILE;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0829e0d3b2d1..eb44e3dfee09 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2681,6 +2681,20 @@ static inline pte_t mk_pte(const struct page *page, pgprot_t pgprot)
return pfn_pte(page_to_pfn(page), pgprot);
}
+/**
+ * pte_folio - Return the folio mapped by a present PTE.
+ * @pte: A present page table entry.
+ *
+ * The folio companion to pte_page(); only meaningful for a present PTE
+ * that maps a struct-page-backed folio.
+ *
+ * Return: The folio containing the page @pte maps.
+ */
+static inline struct folio *pte_folio(pte_t pte)
+{
+ return page_folio(pte_page(pte));
+}
+
/**
* folio_mk_pte - Create a PTE for this folio
* @folio: The folio to create a PTE for
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index dded1768193a..bceab8e14118 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5280,7 +5280,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
* are about to unmap is the actual folio of interest.
*/
if (folio_provided) {
- if (folio != page_folio(pte_page(pte))) {
+ if (folio != pte_folio(pte)) {
spin_unlock(ptl);
continue;
}
@@ -5291,7 +5291,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
*/
set_vma_resv_flags(vma, HPAGE_RESV_UNMAPPED);
} else {
- folio = page_folio(pte_page(pte));
+ folio = pte_folio(pte);
}
pte = huge_ptep_get_and_clear(mm, address, ptep, sz);
@@ -5514,7 +5514,7 @@ static vm_fault_t hugetlb_wp(struct vm_fault *vmf)
return 0;
}
- old_folio = page_folio(pte_page(pte));
+ old_folio = pte_folio(pte);
delayacct_wpcopy_start();
@@ -6189,7 +6189,7 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
* checks whether we can re-use the folio exclusively
* for us in case we are the only user of it.
*/
- folio = page_folio(pte_page(vmf.orig_pte));
+ folio = pte_folio(vmf.orig_pte);
if (folio_test_anon(folio) && !folio_trylock(folio)) {
need_wait_lock = true;
goto out_ptl;
--
2.54.0