From: "Kiryl Shutsemau (Meta)" <[email protected]> Every caller of the engine holds a reference on mm_users for as long as it works: khugepaged for a pass, MADV_COLLAPSE for a call. So mm_users cannot reach zero underneath one, yet collapse.c still asked whether it had, in three places where the answer can only be no.
Ask only whether collapsing was turned off, which prctl() can do at any point, and assert the rest where the interface begins. A caller that arrives without a reference is a bug in the caller. A debug build says so there, rather than leaving it to be found when an address space is freed under a collapse. Assisted-by: Claude-Code:claude-opus-5 Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]> --- mm/collapse.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mm/collapse.c b/mm/collapse.c index 1e3b2d202ffe..28631c734fcb 100644 --- a/mm/collapse.c +++ b/mm/collapse.c @@ -473,7 +473,7 @@ static enum scan_result collapse_revalidate(struct vm_area_struct *vma, enum scan_result result; unsigned int i, nr_live = 0; - if (unlikely(collapse_test_exit_or_disable(mm))) + if (unlikely(collapse_disabled(mm))) return SCAN_ANY_PROCESS; if (!vma->anon_vma || !vma_is_anonymous(vma)) @@ -3731,7 +3731,7 @@ static enum scan_result collapse_file_pmd(struct mm_struct *mm, if (result == SCAN_PTE_MAPPED_HUGEPAGE) { mmap_read_lock(mm); - if (collapse_test_exit_or_disable(mm)) + if (collapse_disabled(mm)) result = SCAN_ANY_PROCESS; else result = try_collapse_pte_mapped_thp(mm, addr, @@ -3762,6 +3762,8 @@ bool collapse_scan_pmd(struct vm_area_struct *vma, unsigned long addr, struct mm_struct *mm = vma->vm_mm; vma_assert_locked(vma); + /* The caller holds a reference on it, so it cannot have gone away */ + VM_WARN_ON_ONCE(collapse_test_exit(mm)); /* * What the scan answers with, so cleared before it runs. @@ -3776,7 +3778,7 @@ bool collapse_scan_pmd(struct vm_area_struct *vma, unsigned long addr, cc->scan_file = NULL; } - if (unlikely(collapse_test_exit_or_disable(mm))) + if (unlikely(collapse_disabled(mm))) cc->scan_refusal = SCAN_ANY_PROCESS; else if (addr < vma->vm_start || end > vma->vm_end) cc->scan_refusal = SCAN_ADDRESS_RANGE; -- 2.54.0
