On Thu, Jun 11, 2026 at 08:42:28AM +0800, Baolin Wang wrote:
>
>
>On 6/10/26 8:44 PM, Lance Yang wrote:
>> 
>> On Wed, Jun 10, 2026 at 06:29:12PM +0800, Baolin Wang wrote:
>> [...]
>>> @@ -1512,8 +1517,12 @@ static enum scan_result mthp_collapse(struct 
>>> mm_struct *mm,
>>>                     enum scan_result ret;
>>>
>>>                     collapse_address = address + offset * PAGE_SIZE;
>>> -                   ret = collapse_huge_page(mm, collapse_address, 
>>> referenced,
>>> -                                            unmapped, cc, order);
>>> +                   if (file)
>>> +                           ret = collapse_file(mm, collapse_address, file,
>>> +                                           start + offset, cc, order);
>>> +                   else
>>> +                           ret = collapse_huge_page(mm, collapse_address,
>>> +                                           referenced, unmapped, cc, 
>>> order);
>>>
>>>                     switch (ret) {
>>>                     /* Cases where we continue to next collapse candidate */
>>> @@ -1521,6 +1530,7 @@ static enum scan_result mthp_collapse(struct 
>>> mm_struct *mm,
>>>                             collapsed += nr_ptes;
>>>                             fallthrough;
>>>                     case SCAN_PTE_MAPPED_HUGEPAGE:
>> 
>> Looks like SCAN_PTE_MAPPED_HUGEPAGE from collapse_file() get lost for
>> the PMD-order case.
>> 
>> Previously, collapse_file() returned it straight back to
>> collapse_single_pmd(), so we would run try_collapse_pte_mapped_thp().
>> 
>> Now it hits mthp_collapse() fitst, and that case just goes to
>> next_offset ...
>
>This is the expected behavior. SCAN_PTE_MAPPED_HUGEPAGE is only returned 
>when the MADV_COLLAPSE collapse succeeds. In this case, if 
>collapse_file() still returns SCAN_PTE_MAPPED_HUGEPAGE, then 
>mthp_collapse() will ultimately return SCAN_FAIL (because collapsed == 
>0), even though the MADV_COLLAPSE collapse has already succeeded.
>
>Additionally, the SCAN_PTE_MAPPED_HUGEPAGE logic is already handled in 
>collapse_scan_file(), see:
>
>result = mthp_collapse(mm, file, start, addr, 0, 0, cc, enabled_orders);
>if (result == SCAN_SUCCEED && !cc->is_khugepaged) {
>         /* If MADV_COLLAPSE, adjust result to call 
>collapse_pte_mapped_thp(). */
>         result = SCAN_PTE_MAPPED_HUGEPAGE;
>}

Right, I agree for that case. The one I meant is a bit different.

I was looking at this earlier return from collapse_file():

                if (is_pmd_order(folio_order(folio))) {
                        result = SCAN_PTE_MAPPED_HUGEPAGE;
                        goto out_unlock;
                }

Old code let it bubble back up:

collapse_single_pmd()
  -> collapse_scan_file()
    -> collapse_file()
      -> SCAN_PTE_MAPPED_HUGEPAGE
    -> SCAN_PTE_MAPPED_HUGEPAGE
  -> try_collapse_pte_mapped_thp()

Not limited to !is_khugepaged. collapse_single_pmd() only checked the
result, then passed !cc->is_khugepaged as install_pmd.

Now the same return goes through mthp_collapse() first:

collapse_single_pmd()
  -> collapse_scan_file()
    -> mthp_collapse()
      -> collapse_file()
        -> SCAN_PTE_MAPPED_HUGEPAGE
      -> goto next_offset

So collapse_single_pmd() never sees SCAN_PTE_MAPPED_HUGEPAGE for this
case anymore. Hopefully Im not missing something here :)

Cheers, Lance

Reply via email to