[RFC v2 08/21] mm: thp: handle split failure in follow_pmd_mask()
From: Usama Arif
Date: Thu Feb 26 2026 - 06:37:59 EST
follow_pmd_mask() splits a huge PMD when FOLL_SPLIT_PMD is set, so GUP
can pin individual pages at PTE granularity.
If the split fails, the PMD is still huge and follow_page_pte() cannot
process it. Return ERR_PTR(-ENOMEM) on split failure, which causes the
GUP caller to get -ENOMEM. -ENOMEM is already returned in follow_pmd_mask
if pte_alloc_one fails (which is the reason why split_huge_pmd could
fail), hence this is a safe change.
Signed-off-by: Usama Arif <usama.arif@xxxxxxxxx>
---
mm/gup.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/mm/gup.c b/mm/gup.c
index 8e7dc2c6ee738..792b2e7319dd0 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -928,8 +928,16 @@ static struct page *follow_pmd_mask(struct vm_area_struct *vma,
return follow_page_pte(vma, address, pmd, flags);
}
if (pmd_trans_huge(pmdval) && (flags & FOLL_SPLIT_PMD)) {
+ int ret;
+
spin_unlock(ptl);
- split_huge_pmd(vma, pmd, address);
+ /*
+ * If split fails, the PMD is still huge and
+ * we cannot proceed to follow_page_pte.
+ */
+ ret = split_huge_pmd(vma, pmd, address);
+ if (ret)
+ return ERR_PTR(ret);
/* If pmd was left empty, stuff a page table in there quickly */
return pte_alloc(mm, pmd) ? ERR_PTR(-ENOMEM) :
follow_page_pte(vma, address, pmd, flags);
--
2.47.3