From aa72cf34d90da7019591ab67533a8ece8b41da2d Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Sat, 31 Oct 2026 10:39:44 +0100 Subject: [PATCH] mm/khugepaged: always recheck the pmd in try_collapse_pte_mapped_thp() try_collapse_pte_mapped_thp() drops the PTE lock after it has cleared the page table, and takes the PMD lock and the PTE lock to remove it. In between, MADV_DONTNEED with CONFIG_PT_RECLAIM can reclaim the page table. The pmd_same() check is supposed to handle this, but it is only done with CONFIG_SPLIT_PTE_PTLOCKS. Fix it by performing the check unconditionally. Fix generated by an LLM and sent by Josef Bacik in private. Fixes: 6375e95f381e ("mm: pgtable: reclaim empty PTE page in madvise(MADV_DONTNEED)") Cc: stable@vger.kernel.org Signed-off-by: Josef Bacik [ david: adjust description ] Reviewed-by: Gregory Price (Meta) Tested-by: Gregory Price (Meta) Tested-by: Muhammad Usama Anjum Link: https://patch.msgid.link/20261031-fixes_core-v3-15-d6437171ecc3@kernel.org Reviewed-by: Lance Yang Reviewed-by: Baolin Wang Signed-off-by: David Hildenbrand (Arm) --- mm/khugepaged.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 3a6f4b7b2845..81496887d827 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -2013,12 +2013,11 @@ static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsign /* step 4: remove empty page table */ if (!pml) { pml = pmd_lock(mm, pmd); - if (ptl != pml) { + if (ptl != pml) spin_lock_nested(ptl, SINGLE_DEPTH_NESTING); - if (unlikely(!pmd_same(pgt_pmd, pmdp_get_lockless(pmd)))) { - flush_tlb_mm(mm); - goto unlock; - } + if (unlikely(!pmd_same(pgt_pmd, pmdp_get_lockless(pmd)))) { + flush_tlb_mm(mm); + goto unlock; } } pgt_pmd = pmdp_collapse_flush(vma, haddr, pmd);