Re: [PATCH v4 0/2] mm: improve folio refcount scalability

From: David Hildenbrand (Arm)

Date: Mon Jun 22 2026 - 04:22:24 EST


On 6/21/26 06:46, Linus Torvalds wrote:
> On Sat, 20 Jun 2026 at 11:19, <ilya.gladyshev@xxxxxxxxx> wrote:
>>
>> T2: optimistic get() [0 -> 1]
>> T2: put page back [1 -> 0]
>> T2: calls dtor for type X, returns into the allocator
>
> Which optimistic getter does this?
>
> I didn't go back and look at the series, but isn't the rule that the code does:
>
> - optimistic get
>
> - then check that the folio is still valid (*not* using the page
> count, but by re-looking it up elsewhere, typically the address space
> mapping)
>
> - put the page if it wasn't valid
>
> - if it goes to zero, there's no destructor inherent in that

I'm also confused about the destructor aspect. Usually we have

folio_try_get(folio)

... some checks

folio_put(folio);

folio_put() is just:

if (folio_put_testzero(folio))
__folio_put(folio);


If the thing was a folio at the start, but stopped being a folio halfway through
folio_put(), I don't see the big difference to the thing not being a folio right
from the start. (folio_try_get() would succeed on some random page either way
right now)

Which destructors are we concerned about?

(1) hugetlb destructor

If we grabbed a non-hugetlb folio but suddenly have a hugetlb folio after
folio_put_testzero(), __folio_put() will just do the right thing and call
free_huge_folio().


(2) pagetable_dtor()

These destructors are called when we unmap the page table, before actually
freeing it. So it wouldn't apply here.


Maybe it's about something like

void page_frag_free(void *addr)
{
struct page *page = virt_to_head_page(addr);

if (unlikely(put_page_testzero(page)))
free_frozen_pages(page, compound_order(page));
}

Whereby, if it's a folio, we wouldn't do the right thing as we are
not going through __folio_put()?

--
Cheers,

David