From: Hugh Dickins <hughd@google.com>
To: Kiryl Shutsemau <kas@kernel.org>
Cc: Hugh Dickins <hughd@google.com>,
Andrew Morton <akpm@linux-foundation.org>,
Ackerley Tng <ackerleytng@google.com>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Alexandre Ghiti <alex@ghiti.fr>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Barry Song <baohua@kernel.org>,
Binbin Wu <binbin.wu@linux.intel.com>,
Christian Brauner <brauner@kernel.org>,
Christoph Hellwig <hch@lst.de>,
Christoph Lameter <cl@gentwo.org>,
Claudio Imbrenda <imbrenda@linux.ibm.com>,
David Hildenbrand <david@kernel.org>,
JP Kobryn <jp.kobryn@linux.dev>, Jan Kara <jack@suse.cz>,
Jens Axboe <axboe@kernel.dk>,
Johannes Weiner <hannes@cmpxchg.org>,
Kairui Song <ryncsn@gmail.com>,
Lance Yang <lance.yang@linux.dev>,
Leonardo Bras <leobras.c@gmail.com>,
Lorenzo Stoakes <ljs@kernel.org>,
Marcelo Tosatti <mtosatti@redhat.com>,
Matthew Wilcox <willy@infradead.org>,
Mel Gorman <mgorman@techsingularity.net>,
Miaohe Lin <linmiaohe@huawei.com>,
Michal Hocko <mhocko@suse.com>, Minchan Kim <minchan@kernel.org>,
Muchun Song <muchun.song@linux.dev>,
Oscar Salvador <osalvador@suse.de>,
Peter Zijlstra <peterz@infradead.org>,
Qi Zheng <qi.zheng@linux.dev>, Rik van Riel <riel@surriel.com>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Shakeel Butt <shakeel.butt@linux.dev>,
Suren Baghdasaryan <surenb@google.com>,
Vlastimil Babka <vbabka@kernel.org>,
Yang Shi <yang@os.amperecomputing.com>,
Yu Zhao <yuzhao@google.com>, Zach O'Keefe <zokeefe@google.com>,
Zi Yan <ziy@nvidia.com>,
linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org
Subject: Re: [PATCH v2 07/26] mm/fbatch: LRU_NEXT_ACTIVATE bit to optimize folio_activate()
Date: Mon, 14 Sep 2026 13:19:37 -0700 (PDT) [thread overview]
Message-ID: <5bd863e9-30a3-c01a-dc8c-c3802b864a6c@google.com> (raw)
In-Reply-To: <84fecd13-f1e4-7d40-94c9-963f5c2f7aee@google.com>
On Sat, 12 Sep 2026, Hugh Dickins wrote:
> On Thu, 10 Sep 2026, Kiryl Shutsemau wrote:
> > On Wed, Sep 09, 2026 at 02:55:41AM -0700, Hugh Dickins wrote:
...
> > > 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
> > > };
> > >
> > > @@ -358,6 +359,9 @@ bool lru_add_del_folio(struct folio *folio)
> > > if (!(lru_next & BIT(LRU_NEXT_BATCHED)))
> > > return false;
> > >
> > > + if (lru_next & BIT(LRU_NEXT_ACTIVATE))
> > > + folio_set_active(folio);
> > > +
> > > WRITE_ONCE(folio->lru.next, LIST_POISON1);
> > > /* BUG_ON(folio->lru_next & BIT(LRU_NEXT_BATCHED)); */
> > >
> > > diff --git a/mm/folio.c b/mm/folio.c
> > > index a18d8ef6afd5..0b75c3b69d5a 100644
> > > --- a/mm/folio.c
> > > +++ b/mm/folio.c
> > > @@ -256,15 +256,32 @@ static void lru_activate(struct lruvec *lruvec, struct folio *folio)
> > >
> > > void folio_activate(struct folio *folio)
> > > {
> > > + unsigned long lru_next;
> > > +
> > > if (folio_test_active(folio) || folio_test_unevictable(folio) ||
> > > !folio_test_lru(folio))
> > > return;
> > >
> > > /*
> > > - * XXX: It is curiously difficult to recreate safely the old
> > > - * __lru_cache_activate_folio() optimization (folio_set_active()
> > > - * directly if it's on the local lru_add fbatch): revisit later.
> > > + * This optimization is intended for the common case of folio
> > > + * having been recently added to this CPU's lru_add fbatch.
> > > + * But since other CPUs can now take it at any instant (after
> > > + * a folio_test_clear_lru()), and we may be migrated to another
> > > + * CPU, it is simplest just to extend the optimization to all CPUs.
> > > + *
> > > + * folio_set_active() would be unsafe without the lruvec lock, and
> > > + * a folio_test_clear_lru() here might cause a racing drain of the
> > > + * lru_add fbatch to skip its lru_add(): so use try_cmpxchg().
> > > */
> > > + lru_next = READ_ONCE(folio->lru_next);
> > > + while (lru_next & BIT(LRU_NEXT_BATCHED)) {
> > > + if (lru_next & BIT(LRU_NEXT_ACTIVATE))
> > > + return;
> > > + if (try_cmpxchg(&folio->lru_next, &lru_next,
> > > + lru_next | BIT(LRU_NEXT_ACTIVATE)))
> > > + return;
> >
> > Hm. What prevents the folio from becoming unevictable under us here?
> > I don't see anything.
> >
> > __folio_add_lru() wouldn't like it:
> >
> > VM_BUG_ON_FOLIO(folio_test_active(folio) &&
> > folio_test_unevictable(folio), folio);
> >
> > folio_lru_list() has the VM_BUG() too.
>
> You're right, thank you. I thought I had deleted all such VM_BUG_ONs:
> and indeed I had, but only in a patch I later decided was too much for
> this series (removing PG_unevictable, using !folio_evictable() in some
> places, or folio_test_unevictable() testing another POISON in lru_next).
>
> That excuse is not enough for this series! Yes, I must send a fixup,
> but not today.
>
> >
> > I am not sure what the right fix is.
> >
> > Maybe lru_add_del_folio() should only call folio_set_active() on
> > !folio_test_unevictable() folios?
I was writing the commit message to a 7.1/26 fixup patch,
when I found I just could not describe any possible race here.
(And I was using your first suggestion, above: in the longer term I
prefer what I chose below, but decided it was better not to get into
that now: deleting various VM_BUG_ON_FOLIOs is better argued elsewhere.
There's another of them in folio_migrate_flags().)
folio_activate() has just checked !folio_test_unevictable(), so
it would have to be a race with something which sets the unevictable
flag on this folio at the same time as we find it's LRU_NEXT_BATCHED.
!folio_evictable() might become true at any instant,
but folio_test_unevictable()?
I cannot see what the racer could be: can you? I can see lru_add()
making it unevictable afterwards; and I can see folio migration
(successful or not) carrying unevictable forwards (or setting it
on a freshly allocated folio). But I cannot see any risky race
for folio_activate() or folio_mark_accessed() here.
Hugh
> >
> > Or should we allow occasional active+unevictable
>
> Yes, that's what I did, just removed the VM_BUG_ONs: but I'll need
> to check again whether that other patch also had to fix any ordering
> of checks. Offhand, probably not: once the "Unevictable LRU" became
> an oopsing fiction, it was important to check unevictable first:
> unevictable must take precedence, and then it really doesn't matter
> whether active is set or not.
>
> > so if they are
> > munlocked, they will go directly to active list?
>
> I didn't think of that, but I don't think that "active", set racily
> back when the folio was assigned "unevictable", bears much relation
> to whether it ought to be put on active or inactive list when later
> made evictable again. We should probably be consistent, and
> consistent with existing behaviour, that they go to inactive when
> made evictable. (I'm not looking at that other patch at present,
> I don't recall where active got cleared in it.)
>
> Hugh
next prev parent reply other threads:[~2026-09-14 20:19 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-09 9:39 [PATCH v2 00/26] mm/fbatch: drain lru_add_drain() and _all() Hugh Dickins
2026-09-09 9:42 ` [PATCH v2 01/26] mm/fbatch: remove !CONFIG_SMP special case of folio_activate() Hugh Dickins
2026-09-09 9:44 ` [PATCH v2 02/26] mm/fbatch: allow folios_put_refs() to skip xa_is_value() entries Hugh Dickins
2026-09-09 9:46 ` [PATCH v2 03/26] mm/fbatch: temporarily disable lazyfree and mlock+munlock batching Hugh Dickins
2026-09-09 9:49 ` [PATCH v2 04/26] mm/fbatch: lru bit set, no extra ref, while folio on per-cpu fbatch Hugh Dickins
2026-09-09 12:25 ` Vlastimil Babka (SUSE)
2026-09-12 19:30 ` Hugh Dickins
2026-09-09 9:51 ` [PATCH v2 05/26] mm/fbatch: lru_add_del_folio()+folio_add_lru() after clear_lru() Hugh Dickins
2026-09-09 15:04 ` Vlastimil Babka (SUSE)
2026-09-12 21:59 ` Hugh Dickins
2026-09-09 9:53 ` [PATCH v2 06/26] mm/fbatch: fbatch_drain_lazyfree(onstack fbatch) before ptl unlock Hugh Dickins
2026-09-09 21:02 ` Vlastimil Babka (SUSE)
2026-09-12 22:07 ` Hugh Dickins
2026-09-09 9:55 ` [PATCH v2 07/26] mm/fbatch: LRU_NEXT_ACTIVATE bit to optimize folio_activate() Hugh Dickins
2026-09-10 12:01 ` Vlastimil Babka (SUSE)
2026-09-12 22:35 ` Hugh Dickins
2026-09-14 19:55 ` Hugh Dickins
2026-09-10 16:42 ` Kiryl Shutsemau
2026-09-12 23:33 ` Hugh Dickins
2026-09-14 20:19 ` Hugh Dickins [this message]
2026-09-15 13:08 ` Kiryl Shutsemau
2026-09-09 9:57 ` [PATCH v2 08/26] mm/fbatch: replace mlock_new_folio() by __folio_add_lru(,mlockit) Hugh Dickins
2026-09-10 17:47 ` Vlastimil Babka (SUSE)
2026-09-09 9:59 ` [PATCH v2 09/26] mm/fbatch: restore mlock+munlock batching, without extra ref Hugh Dickins
2026-09-10 21:05 ` Vlastimil Babka (SUSE)
2026-09-12 23:46 ` Hugh Dickins
2026-09-14 8:16 ` Vlastimil Babka (SUSE)
2026-09-09 10:01 ` [PATCH v2 10/26] mm/fbatch: remove several uses of mlock_drain_local() Hugh Dickins
2026-09-09 10:03 ` [PATCH v2 11/26] mm/fbatch: remove migration's PAGE_WAS_MLOCKED lru_add_drain() Hugh Dickins
2026-09-09 10:05 ` [PATCH v2 12/26] mm/fbatch: remove percpu_pvec_drained and folios_put() Hugh Dickins
2026-09-09 10:08 ` [PATCH v2 13/26] mm/fbatch: no lru_add_drain to collect_longterm_unpinnable_folios() Hugh Dickins
2026-09-09 10:10 ` [PATCH v2 14/26] mm/fbatch: no lru_add_drain() nor _all() for memfd_wait_for_pins() Hugh Dickins
2026-09-09 10:12 ` [PATCH v2 15/26] mm/fbatch: remove shake_folio() shake_page() from memory-failure Hugh Dickins
2026-09-09 10:14 ` [PATCH v2 16/26] mm/fbatch: remove lru_cache_disable() from NUMA folio migration Hugh Dickins
2026-09-09 10:16 ` [PATCH v2 17/26] mm/fbatch: no lru_cache_disable() in __alloc_contig_migrate_range() Hugh Dickins
2026-09-09 10:18 ` [PATCH v2 18/26] mm/fbatch: remove lru_add_drain() and _all() calls from various Hugh Dickins
2026-09-09 10:20 ` [PATCH v2 19/26] mm/fbatch: vm/stat_refresh include lru_add_drain() on each cpu Hugh Dickins
2026-09-09 10:23 ` [PATCH v2 20/26] s390/fbatch: no lru_add_drain_all() in s390_wiggle_split_folio() Hugh Dickins
2026-09-09 10:25 ` [PATCH v2 21/26] block/fbatch: no lru_add_drain_all() in invalidate_bdev() Hugh Dickins
2026-09-09 10:27 ` [PATCH v2 22/26] fs/fbatch: drop_caches invalidate_bh_lrus() not lru_add_drain_all() Hugh Dickins
2026-09-09 10:30 ` [PATCH v2 23/26] fs,mm/fbatch: use invalidate_bh_lrus() not invalidate_bh_lrus_cpu() Hugh Dickins
2026-09-09 10:33 ` [PATCH v2 24/26] fs,mm/fbatch: lru_cache_disable() keep off buffer_head lrus only Hugh Dickins
2026-09-09 10:35 ` [PATCH v2 25/26] mm/fbatch: move lru_add_drain_all() declaration to mm/internal.h Hugh Dickins
2026-09-09 10:37 ` [PATCH v2 26/26] mm/fbatch: drop reference inside the loop when draining Hugh Dickins
2026-09-09 10:41 ` [PATCH v2 27/26] mm/fbatch: paranoid folio vmstats in folio_batch_move_lru() Hugh Dickins
2026-09-26 2:07 ` [PATCH v2 00/26] mm/fbatch: drain lru_add_drain() and _all() JP Kobryn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5bd863e9-30a3-c01a-dc8c-c3802b864a6c@google.com \
--to=hughd@google.com \
--cc=ackerleytng@google.com \
--cc=akpm@linux-foundation.org \
--cc=alex@ghiti.fr \
--cc=axboe@kernel.dk \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=bigeasy@linutronix.de \
--cc=binbin.wu@linux.intel.com \
--cc=brauner@kernel.org \
--cc=cl@gentwo.org \
--cc=david@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=hch@lst.de \
--cc=imbrenda@linux.ibm.com \
--cc=jack@suse.cz \
--cc=jp.kobryn@linux.dev \
--cc=kas@kernel.org \
--cc=lance.yang@linux.dev \
--cc=leobras.c@gmail.com \
--cc=linmiaohe@huawei.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mgorman@techsingularity.net \
--cc=mhocko@suse.com \
--cc=minchan@kernel.org \
--cc=mtosatti@redhat.com \
--cc=muchun.song@linux.dev \
--cc=osalvador@suse.de \
--cc=peterz@infradead.org \
--cc=qi.zheng@linux.dev \
--cc=riel@surriel.com \
--cc=ryncsn@gmail.com \
--cc=shakeel.butt@linux.dev \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=viro@zeniv.linux.org.uk \
--cc=willy@infradead.org \
--cc=yang@os.amperecomputing.com \
--cc=yuzhao@google.com \
--cc=ziy@nvidia.com \
--cc=zokeefe@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.