Re: [RFC PATCH 2/2] mm: implement page refcount locking via dedicated bit

From: Gladyshev Ilya

Date: Fri Dec 19 2025 - 11:19:04 EST


On 12/19/2025 5:50 PM, Kiryl Shutsemau wrote:
On Fri, Dec 19, 2025 at 12:46:39PM +0000, Gladyshev Ilya wrote:
The current atomic-based page refcount implementation treats zero
counter as dead and requires a compare-and-swap loop in folio_try_get()
to prevent incrementing a dead refcount. This CAS loop acts as a
serialization point and can become a significant bottleneck during
high-frequency file read operations.

This patch introduces FOLIO_LOCKED_BIT to distinguish between a

s/FOLIO_LOCKED_BIT/PAGEREF_LOCKED_BIT/
Ack, thanks

(temporary) zero refcount and a locked (dead/frozen) state. Because now
incrementing counter doesn't affect it's locked/unlocked state, it is
possible to use an optimistic atomic_fetch_add() in
page_ref_add_unless_zero() that operates independently of the locked bit.
The locked state is handled after the increment attempt, eliminating the
need for the CAS loop.

I don't think I follow.

Your trick with the PAGEREF_LOCKED_BIT helps with serialization against
page_ref_freeze(), but I don't think it does anything to serialize
against freeing the page under you.

Like, if the page in the process of freeing, page allocator sets its
refcount to zero and your version of page_ref_add_unless_zero()
successfully acquirees reference for the freed page.

How is it safe?

Page is freed only after a successful page_ref_dec_and_test() call, which will set LOCKED_BIT. This bit will persist until set_page_count(1) is called somewhere in the allocation path [alloc_pages()], and effectively block any "use after free" users.