[RFC v2 05/21] mm: thp: handle split failure in zap_pmd_range()
Usama Arif
usama.arif at linux.dev
Thu Feb 26 22:23:34 AEDT 2026
zap_pmd_range() splits a huge PMD when the zap range doesn't cover the
full PMD (partial unmap). If the split fails, the PMD stays huge.
Falling through to zap_pte_range() would dereference the huge PMD entry
as a PTE page table pointer.
Skip the range covered by the PMD on split failure instead.
The skip is safe across all call paths into zap_pmd_range():
- exit_mmap() and OOM reaper: the zap range covers entire VMAs, so
every PMD is fully covered (next - addr == HPAGE_PMD_SIZE). The
zap_huge_pmd() branch handles these without splitting. The split
failure path is unreachable.
- munmap / mmap overlay: vma_adjust_trans_huge() (called from
__split_vma) splits any PMD straddling the VMA boundary before the
VMA is split. If that PMD split fails, __split_vma() returns
-ENOMEM and the munmap is aborted before reaching zap_pmd_range().
The split failure path is unreachable.
- MADV_DONTNEED: advisory hint, the kernel is allowed to ignore it.
The pages remain valid and accessible. A subsequent access returns
existing data without faulting.
Signed-off-by: Usama Arif <usama.arif at linux.dev>
---
mm/memory.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index 9385842c35034..7ba1221c63792 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1983,9 +1983,18 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb,
do {
next = pmd_addr_end(addr, end);
if (pmd_is_huge(*pmd)) {
- if (next - addr != HPAGE_PMD_SIZE)
- __split_huge_pmd(vma, pmd, addr, false);
- else if (zap_huge_pmd(tlb, vma, pmd, addr)) {
+ if (next - addr != HPAGE_PMD_SIZE) {
+ /*
+ * If split fails, the PMD stays huge.
+ * Skip the range to avoid falling through
+ * to zap_pte_range, which would treat the
+ * huge PMD entry as a page table pointer.
+ */
+ if (__split_huge_pmd(vma, pmd, addr, false)) {
+ addr = next;
+ continue;
+ }
+ } else if (zap_huge_pmd(tlb, vma, pmd, addr)) {
addr = next;
continue;
}
--
2.47.3
More information about the Linuxppc-dev
mailing list