On 5/22/26 17:00, Nico Pache wrote:
> Pass an order and offset to collapse_huge_page to support collapsing anon
> memory to arbitrary orders within a PMD. order indicates what mTHP size we
> are attempting to collapse to, and offset indicates were in the PMD to
> start the collapse attempt.
> 
> For non-PMD collapse we must leave the anon VMA write locked until after
> we collapse the mTHP-- in the PMD case all the pages are isolated, but in
> the mTHP case this is not true, and we must keep the lock to prevent
> access/changes to the page tables. This can happen if the rmap walkers hit
> a pmd_none while the PMD entry is currently unavailable due to being
> temporarily removed during the collapse phase.
> 
> Acked-by: Usama Arif <[email protected]>
> Signed-off-by: Nico Pache <[email protected]>
> ---

I guess we should add a comment here like:

/*
 * Only notify about the PTE range we will actually modify. While we
 * temporary unmap the whole PTE table for mTHP collapse, we'll remap
 * it later, leaving other PTEs effectively unmodified. The locks we hold
 * prevent anybody from stumbling over such temporarily unmapped PTE tables.
 */

>  
> -     mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, address,
> -                             address + HPAGE_PMD_SIZE);
> +     mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, start_addr,
> +                             end_addr);
>       mmu_notifier_invalidate_range_start(&range);
>  
>       pmd_ptl = pmd_lock(mm, pmd); /* probably unnecessary */
> @@ -1294,26 +1297,23 @@ static enum scan_result collapse_huge_page(struct 
> mm_struct *mm, unsigned long a
>        * Parallel GUP-fast is fine since GUP-fast will back off when
>        * it detects PMD is changed.
>        */
> -     _pmd = pmdp_collapse_flush(vma, address, pmd);
> +     _pmd = pmdp_collapse_flush(vma, pmd_addr, pmd);
>       spin_unlock(pmd_ptl);
>       mmu_notifier_invalidate_range_end(&range);
>       tlb_remove_table_sync_one();
>  
> -     pte = pte_offset_map_lock(mm, &_pmd, address, &pte_ptl);
> +     pte = pte_offset_map_lock(mm, &_pmd, start_addr, &pte_ptl);
>       if (pte) {
> -             result = __collapse_huge_page_isolate(vma, address, pte, cc,
> -                                                   HPAGE_PMD_ORDER,
> -                                                   &compound_pagelist);
> +             result = __collapse_huge_page_isolate(vma, start_addr, pte, cc,
> +                                                   order, 
> &compound_pagelist);
>               spin_unlock(pte_ptl);
>       } else {
>               result = SCAN_NO_PTE_TABLE;
>       }
>  
>       if (unlikely(result != SCAN_SUCCEED)) {
> -             if (pte)
> -                     pte_unmap(pte);
>               spin_lock(pmd_ptl);
> -             BUG_ON(!pmd_none(*pmd));
> +             WARN_ON_ONCE(!pmd_none(*pmd));

Likely VM_WARN_ON_ONCE is sufficient.

>               /*
>                * We can only use set_pmd_at when establishing
>                * hugepmds and never for establishing regular pmds that
> @@ -1321,21 +1321,24 @@ static enum scan_result collapse_huge_page(struct 
> mm_struct *mm, unsigned long a
>                */
>               pmd_populate(mm, pmd, pmd_pgtable(_pmd));
>               spin_unlock(pmd_ptl);
> -             anon_vma_unlock_write(vma->anon_vma);
>               goto out_up_write;
>       }
>  
>       /*
> -      * All pages are isolated and locked so anon_vma rmap
> -      * can't run anymore.
> +      * For PMD collapse all pages are isolated and locked so anon_vma
> +      * rmap can't run anymore. For mTHP collapse the PMD entry has been
> +      * removed and not all pages are isolated and locked, so we must hold
> +      * the lock to prevent neighboring folios from attempting to access
> +      * this PMD until its reinstalled.
>        */

That makes sense. I was wondering whether there was another reason for dropping
the anon_vma lock ... I guess it was just for latency purposes given that there
was no actual need for the lock anymore once all folios in the range were
isolate+locked.


With the two its above addressed

Acked-by: David Hildenbrand (arm) <[email protected]>

-- 
Cheers,

David

Reply via email to