Re: [PATCH] mm/khugepaged: Don't collapse uffd-minor-registered VMAs

From: James Houghton

Date: Fri Aug 28 2026 - 15:08:21 EST


On Fri, Aug 28, 2026 at 2:47 AM Lance Yang <lance.yang@xxxxxxxxx> wrote:
>
> On Fri, Aug 28, 2026 at 12:50:04AM +0000, James Houghton wrote:
> >Userfaultfd minor faults provides userspace with the ability to manually
> >install PTEs with UFFDIO_CONTINUE. Right now, khugepaged collapse can
> >map holes in the VMA when a naturally-aligned THP is present without
> >explicit action from userspace.
> >
> >This is a problem, as it bypasses userfaultfd minor faults that
> >userspace is expecting to handle.
>
> One basic question first. Should MADV_COLLAPSE refuse to collapse a
> UFFD-minor-registered VMA, regardless of whether all PTEs are present?
>
> I'd leave that to the maintainers :D
>
> Anyway, assuming the answer is yes, I wonder whether the new check is
> sufficient. See below.

I also think the answer is yes.

Theoretically you could optimize this and allow userspace to avoid
calling a bunch of UFFDIO_CONTINUEs and instead call MADV_COLLAPSE,
but let's wait for someone (probably won't be me, at least not for a
couple years) to ask for it. But khugepaged's own collapse routines
(and potentially other processes via process_madvise()) should remain
unchanged; that would reintroduce the bug being fixed here.

> static inline bool userfaultfd_minor(struct vm_area_struct *vma)
> {
> return vma_test_any_mask(vma, VMA_UFFD_MINOR);
> }
>
> static inline bool userfaultfd_protected(struct vm_area_struct *vma)
> {
> return userfaultfd_wp(vma) || userfaultfd_rwp(vma);
> }
>
> Emm ... userfaultfd_protected() only covers WP and RWP. MADV_COLLAPSE
> passes install_pmd=true, so the SCAN_NO_PTE_TABLE case can still reach
> set_huge_pmd() after UFFDIO_REGISTER_MODE_MINOR has completed ...
>
> Maybe:
>
> ---8<---
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 33c41bc32af8..0eada7265d59 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -1893,6 +1893,8 @@ static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsign
> */
> if (userfaultfd_protected(vma))
> return SCAN_PTE_UFFD;
> + if (userfaultfd_minor(vma))
> + return SCAN_PTE_UFFD;
>
> folio = filemap_lock_folio(vma->vm_file->f_mapping,
> linear_page_index(vma, haddr));
> --
>
> With that, LGTM.
>
> Tested-by: Lance Yang <lance.yang@xxxxxxxxx>

Thanks, Lance. This is how I should have written the patch to begin
with. :) It addresses both comments that Sashiko left as well.

I'll send a v2 soon. Thank you!