Re: [PATCH v6 3/3] mm: implement page refcount locking via dedicated bit

From: Linus Torvalds

Date: Thu Sep 24 2026 - 16:07:34 EST


On Thu, 24 Sept 2026 at 11:52, David Hildenbrand (Arm) <david@xxxxxxxxxx> wrote:
>
> There needs to be a common page freeing function that dipatches stuff.

I think this all needs to be entirely generic to all pages. Agreed.
Everybody needs to do it right.

But I think that in the scenario that Ilya mentioned:

Refcount operations as follows (FR = FROZEN):

A: DEC 1 -> 0 [ page_ref_dec_and_test() ]
B: INC 0 -> 1 [ folio_try_get() ] => success
B: DEC 1 -> 0 [ page_ref_dec_and_test() ]
B: CAS 0 -> FR [ page_ref_dec_and_test() ]
B: * deallocates via __folio_put() *

C: * re-allocates page *
C: DEC 1 -> 0 [ page_ref_dec_and_test() ]
A: CAS 0 -> FR [ page_ref_dec_and_test() ] => success
A: * deallocates directly via free_frozen_pages() * => BUG

the big here is that the de-allocation was done not from the state of
the *page*, but from the state of who finished it off.

So that

A: CAS 0 -> FR [ page_ref_dec_and_test() ] => success

is not a problem per se. It's a fine case of "we had one single unique
final free".

The failure is that A then goes on to do that

"deallocates directly via free_frozen_pages"

because A mis-judged the page as having the old stale state that it
had when *A* was using it.

IOW, I think the soluition is either:

(a) every user of put_page_testzero(page) agrees tro do exactly the
same thing and there is no difference between how that final
"0->FROZEN" is dealt with, so it doesn't matter that A is freeing a
page that C allocated for something else

or

(b) the CAS 0 -> FR state sequence always looks at the *page* to
decide what to do, never at the caller state (ie A will look at
whatever C wrote when it allocated the page to know how to do that
final free).

Hmm?

Linus