When an anonymous mapping is collapsed for THP, a PTE page table is 'deposited' with the installed PMD entry. This is done in order that a split can be performed without needing to allocate additional memory. The freeing occurs in zap_deposited_table() and is done directly without any delay via pte_free(). This is currently not a problem as existing page table walks are protected by the mmap or anon rmap lock. However this becomes problematic in a future where RCU-only page table walkers exist, as there is nothing to prevent a page table walker that started the walk prior to collapse having its PTE table freed underneath it. Commit 13cf577e6b66 ("mm/pgtable: add pte_free_defer() for pgtable as page") already provides us the mechanism by which to solve this - pte_free_defer(). Therefore, as a prerequisite to a future commit which will permit fully RCU page table walks, update zap_deposited_table() to use pte_free_defer() rather than pte_free(). Note that the IPI sync in collapse_huge_page() is still required to ensure refcount correctness against a GUP-fast operation. This is because GUP-fast might increment refcount, but __collapse_huge_page_isolate() determines whether it is safe to proceed by checking folio_ref_count() against folio_expected_ref_count(), so the two must be mutually excluded. Signed-off-by: Lorenzo Stoakes (ARM) --- mm/huge_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 54494c3fa983..505f7b62ff28 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2476,7 +2476,7 @@ static inline void zap_deposited_table(struct mm_struct *mm, pmd_t *pmd) pgtable_t pgtable; pgtable = pgtable_trans_huge_withdraw(mm, pmd); - pte_free(mm, pgtable); + pte_free_defer(mm, pgtable); mm_dec_nr_ptes(mm); } -- 2.55.0