[v3 15/24] fs/dax: handle split_huge_pmd failure in dax_iomap_pmd_fault

Usama Arif
2026-03-27T02:15:45Z

dax_iomap_pmd_fault() splits a huge PMD when the PMD fault falls back
to PTE-level handling. The split is necessary so that the subsequent
PTE fault does not misinterpret the huge PMD entry as a page table
pointer.

In practice this cannot fail today: DAX VMAs are always file-backed,
and __split_huge_pmd() only allocates a PTE page table (the operation
that can return -ENOMEM) for anonymous VMAs. For file-backed VMAs the
split path simply zaps the PMD and returns 0.

Use WARN_ON_ONCE to document this invariant and check the return value
for __must_check compliance introduced in the next patch.

Signed-off-by: Usama Arif <usama.arif@linux.dev>
---
fs/dax.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/fs/dax.c b/fs/dax.c
index a5237169b4679..ed1859e8a916f 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -2039,7 +2039,14 @@ static vm_fault_t dax_iomap_pmd_fault(struct vm_fault *vmf, unsigned long *pfnp,
dax_unlock_entry(&xas, entry);
fallback:
if (ret == VM_FAULT_FALLBACK) {
- split_huge_pmd(vmf->vma, vmf->pmd, vmf->address);
+ /*
+ * split_huge_pmd() cannot fail for file-backed (DAX) VMAs
+ * since splitting only zaps the PMD without allocating a
+ * PTE page table.
+ */
+ if (WARN_ON_ONCE(split_huge_pmd(vmf->vma, vmf->pmd,
+ vmf->address)))
+ ret = VM_FAULT_OOM;
count_vm_event(THP_FAULT_FALLBACK);
}
out:
--
2.52.0