Re: Improve page refcount scalability
From: Linus Torvalds
Date: Tue Oct 13 2026 - 17:28:16 EST
On Tue, 13 Oct 2026 at 14:03, Matthew Wilcox <willy@xxxxxxxxxxxxx> wrote:
>
> I don't like the PG_rcu_free flag. I hope we're guaranteed that folios
> in the process of being freed by RCU will not be mapped into userspace.
> That means we can use PGTY_rcu instead, where there is no shortage of
> available types.
I don't see how we could ever map a page into user space *while* it's
in the process of being free'd by RCU.
But no, I don't think we can use the PGTY_xyz flags, because while
they won't be mapped into user space during the actual RCU freeing
period, they *would* be marked for being free'd long before that.
Including, very much, while being mmap'ed into user space.
IOW, the trivial way to do it is to mmap a file, and then doin regular
enough regular 'read()' calls on the pages that they get marked as
hot. End result: folio marked as PG_rcu_free while still being mapped.
The RCU freeing itself obviously won't *happen* until after the page
has been unmapped, but the flag needs to be there before.
> The workload that Kiryl identified (truncating/holepunching folios
> from files) is not the normal way we free folios from the page cache
> so while we need to accommodate it, it's not what we shuld optimise for.
I wouldn't cal;l the current case optimized for that. It was the
simplest test-case for quickly removing a lot of pages from the page
cache, and as such it's the *worst* case in many ways.
> Most page cache folios get freed through reclaim. I started sketching
> out a new state (I was going to call them "ghost folios") when I realised
> I was basically reinventing the inactive list. So maybe we should make
> folios on the inactive list immediately freeable as long as one RCU
> generation has passed?
Honestly, I don't think it works. Or rather, you can *force* it to
work, but it won't ever be a good solution. For the simple reason that
you still need to handle this whole "immediate free" case by hole
punching etc.
Hole punching itself may not be the common case - but 'truncate()'
actually *will* be the common case in some situations. It's very easy
to trigger.
So you try to make the different cases (truncate vs reclaim) have
different rules, but I think you will only be making up special cases
and hurting yourself in the process.
End result: I'd put that solidly in the "Doctor, doctor, it hurts when
I punch myself in the face" problem space. The solution is "Don't do
that then", not to try to look for other solutions.
Also, honestly, by now it's been two and a half years of this.
So by now I'd also go: I have a patch series. It's clean. It's ten
patches, each of them cleanly separated, half of them *tiny*, and none
of them more than 150 lines of code. It works.
If you have alternative approaches, I think it's "Show me the
money^Hcode" time, not handwavy "maybe we could do xyz" time.
Linus