Re: [PATCH v2 07/26] mm/fbatch: LRU_NEXT_ACTIVATE bit to optimize folio_activate()

From: Hugh Dickins

Date: Sat Sep 12 2026 - 18:35:37 EST


On Thu, 10 Sep 2026, Vlastimil Babka (SUSE) wrote:
> On 9/9/26 11:55, Hugh Dickins wrote:
> > Implement an equivalent to the old __lru_cache_activate_folio()
> > optimization, to activate a folio recently put in the lru_add fbatch,
> > without having to put it through the lru_activate fbatch too. Neither
> > lruvec lock nor lru bit can guard this safely and efficiently, so resort
> > to try_cmpxchg() on a further, LRU_NEXT_ACTIVATE bit in folio->lru_next.
> >
> > Signed-off-by: Hugh Dickins <hughd@xxxxxxxxxx>
> > ---
> > include/linux/mm_inline.h | 4 ++++
> > mm/folio.c | 23 ++++++++++++++++++++---
> > 2 files changed, 24 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
> > index 8420b1276535..8f5efadf9c7c 100644
> > --- a/include/linux/mm_inline.h
> > +++ b/include/linux/mm_inline.h
> > @@ -346,6 +346,7 @@ static inline void folio_migrate_refs(struct folio *new, const struct folio *old
> > enum {
> > LRU_NEXT_NEVER_TAIL = 0, /* Used by a tail's compound_head */
> > LRU_NEXT_BATCHED = 1, /* Not used by any aligned pointer */
> > + LRU_NEXT_ACTIVATE,
> > NR_LRU_NEXT_FLAGS
> > };
>
> This addition, and the comment "/* This mask will do nothing on 64-bit */"
> in folio_add_lru()... does it mean that now this is breaking 32-bit? Should
> we make this optimization, or perhaps all of the cpu fbatch, 64-bit only?

Answering second question first: those could have been options, to
disable the activation optimization or all per-cpu fbatching, on 32-bit;
but I much preferred them not to diverge, and tried hard to keep 32-bit.

First Q: This does not, in the end, break 32-bit at all. But while I
was developing, I thought it did, and reluctantly switched the encoding
away from holding lru_add entry pointer in lru_next, to holding
lru_add cpu and lru_add index in lru_next: from those the lru_add
entry pointer can easily be calculated, and there's lots of space
left over for more flag bits (which I thought might come to be needed).

But then I had that marvellous realization in folio_batch_move_lru(),
that it needed to service "wrong" entries in exactly the same way as
"right" entries, therefore didn't need to distinguish them, therefore
didn't need any address there at all.

I have kept the address for debugging, and do put it to some use in
the paranoid vmstats patch 27/26. On 32-bit, with 4-byte pointers,
this LRU_NEXT_ACTIVATE bit does then leave one pointer covering two
adjacent entries, when it's deciding whether the folio points back
to this lru_add entry. Is it possible for two adjacent entries to
hold the same folio (and so perhaps miscount the stat)? Yes, it is
possible (if that folio is freed and reused and readded immediately);
but so unlikely that it's of no importance when gathering stats.

Hugh