From: Kiryl Shutsemau <kas@kernel.org>
To: Hugh Dickins <hughd@google.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Ackerley Tng <ackerleytng@google.com>,
Alexander Viro <viro@zeniv.linux.org.uk>,
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 07/25] mm/fbatch: LRU_NEXT_ACTIVATE bit to optimize folio_activate()
Date: Thu, 3 Sep 2026 11:56:15 +0100 [thread overview]
Message-ID: <aplHq9bvNdyPGEw-@thinkstation> (raw)
In-Reply-To: <821cced3-dcc8-6c80-a92c-c568c2639e5a@google.com>
On Wed, Sep 02, 2026 at 10:41:56PM -0700, Hugh Dickins wrote:
> On Mon, 31 Aug 2026, Kiryl Shutsemau wrote:
> > On Fri, Aug 28, 2026 at 01:40:51AM -0700, Hugh Dickins wrote:
> > > Do you have a head for smp_mb__ barriers? I'm more anxious that
> > > I might be missing one or two of those.
> >
> > I think the release side of PG_lru is missing.
> >
> > You effectively turn PG_lru into a lock over folio->lru.next.
> >
> > The acquire side works: test_and_clear_bit() has a return value, so it
> > is fully ordered.
> >
> > But there's a problem with release. set_bit() is unordered. You
> > correctly placed a fence in __folio_add_lru(), but every other
> > folio_set_lru() is problematic.
> >
> > For instance:
> >
> > CPU0 CPU1
> > folio_batch_move_lru() folio_batch_move_lru()
> > lru_add_del_folio()
> > lru.next = LIST_POISON1
> > lruvec lock
> > list_add()
> > /* no barrier */
> > set_bit(PG_lru)
> > folio_try_get() == true
> > folio_test_clear_lru() == true
> > lru_next == stale BATCHED ???
> > lruvec unlock
> >
> > If CPU1 sees a stale BATCHED, lru_add_del_folio() returns true without
> > doing the list_del() or the NR_LRU_BASE accounting, and CPU1 then goes
> > on to lruvec_add_folio() a folio that is already on a list.
> >
> > I think we need to have a helper that would set PG_lru and enforce
> > release semantics.
>
> Thank you very much for this, Kiryl: it helps me considerably.
> But I have to cool myself down close to absolute zero to think
> about these things, and can only manage that occasionally.
>
> I've nothing useful to say yet. I believe I understand you, and in
> particular your last sentence, which I take as an observation that
> clear_bit_unlock() is well-established, but what we want is
> set_bit_unlock(), perhaps better named set_bit_release().
>
> Of course I'm not competent to add that to N architectures, most of
> them unfamiliar to me. So I'm looking for a reasonable compromise,
> to minimize the additional overhead needed for correctness here,
> just using what we have already have (test_and_set, smp_mb__).
It would not be N architectures. This should be good enough:
/* include/asm-generic/bitops/lock.h */
#ifndef arch_set_bit_release
static __always_inline void
arch_set_bit_release(unsigned int nr, volatile unsigned long *p)
{
p += BIT_WORD(nr);
raw_atomic_long_fetch_or_release(BIT_MASK(nr), (atomic_long_t *)p);
}
#endif
/* include/asm-generic/bitops/instrumented-lock.h */
static inline void set_bit_release(long nr, volatile unsigned long *addr)
{
kcsan_release();
instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
arch_set_bit_release(nr, addr);
}
/* arch/x86/include/asm/bitops.h -- mirrors arch_clear_bit_unlock() */
static __always_inline void
arch_set_bit_release(long nr, volatile unsigned long *addr)
{
barrier(); /* LOCK prefix is already a full barrier */
arch_set_bit(nr, addr);
}
#define arch_set_bit_release arch_set_bit_release
I don't know if we want to make it _unlock() to match
clear_bit_unlock(). Naming is hard.
x86 does need an override, since it has no locked OR that returns the old
value -- arch_atomic64_fetch_or() is a cmpxchg loop.
arm64 is happy with the generic version.
ppc and riscv need a definition of their own only because they do not
include asm-generic/bitops/lock.h, so the #ifndef above never reaches
them. ppc can take the generic body. and riscv is a one-liner right next
to its existing arch_clear_bit_unlock().
This set_bit_release() gets better results than alternatives:
set_bit_release() smp_mb__ + set_bit() test_and_set_bit()
x86 lock orb lock orb lock btsq
arm64 LSE ldsetl dmb ish + stset ldsetal
arm64 LL/SC ldxr/stlxr dmb ish + ldxr/stxr ldxr/stlxr + dmb ish
ppc lwsync + loop sync + loop sync + loop + sync
riscv amoor.d.rl fence rw,rw + amoor.d amoor.d.aqrl
I can prepare a proper patches with what I listed above, if you want, so
you can prepend to your series.
If you don't want to go there for the initial series,
smp_mb__before_atomic() plus folio_set_lru() should be good enough:
static __always_inline bool folio_test_clear_lru_acquire(struct folio *folio)
{
return folio_test_clear_lru(folio);
}
static __always_inline void folio_set_lru_release(struct folio *folio)
{
smp_mb__before_atomic();
folio_set_lru(folio);
}
--
Kiryl Shutsemau / Kirill A. Shutemov
next prev parent reply other threads:[~2026-09-03 10:56 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-24 13:49 [PATCH 00/25] mm/fbatch: drain lru_add_drain() and _all() Hugh Dickins
2026-08-24 13:52 ` [PATCH 01/25] mm/fbatch: remove !CONFIG_SMP special case of folio_activate() Hugh Dickins
2026-08-27 17:23 ` David Hildenbrand (Arm)
2026-08-24 13:55 ` [PATCH 02/25] mm/fbatch: allow folios_put_refs() to skip xa_is_value() entries Hugh Dickins
2026-08-27 17:35 ` David Hildenbrand (Arm)
2026-08-24 13:58 ` [PATCH 03/25] mm/fbatch: temporarily disable lazyfree and mlock+munlock batching Hugh Dickins
2026-08-24 14:01 ` [PATCH 04/25] mm/fbatch: lru bit set, no extra ref, while folio on per-cpu fbatch Hugh Dickins
2026-08-27 11:46 ` Kiryl Shutsemau
2026-08-28 8:04 ` Hugh Dickins
2026-08-28 14:40 ` Matthew Wilcox
2026-08-28 22:20 ` Hugh Dickins
2026-09-02 4:05 ` Hugh Dickins
2026-08-24 14:03 ` [PATCH 05/25] mm/fbatch: lru_add_del_folio()+folio_add_lru() after clear_lru() Hugh Dickins
2026-08-24 14:06 ` [PATCH 06/25] mm/fbatch: fbatch_drain_lazyfree(onstack fbatch) before ptl unlock Hugh Dickins
2026-08-24 14:09 ` [PATCH 07/25] mm/fbatch: LRU_NEXT_ACTIVATE bit to optimize folio_activate() Hugh Dickins
2026-08-27 12:02 ` Kiryl Shutsemau
2026-08-28 8:40 ` Hugh Dickins
2026-08-31 2:28 ` Kiryl Shutsemau
2026-09-03 5:41 ` Hugh Dickins
2026-09-03 10:56 ` Kiryl Shutsemau [this message]
2026-09-03 19:08 ` Hugh Dickins
2026-08-24 14:11 ` [PATCH 08/25] mm/fbatch: replace mlock_new_folio() by __folio_add_lru(,mlockit) Hugh Dickins
2026-08-24 14:14 ` [PATCH 09/25] mm/fbatch: restore mlock+munlock batching, without extra ref Hugh Dickins
2026-08-24 14:16 ` [PATCH 10/25] mm/fbatch: remove several uses of mlock_drain_local() Hugh Dickins
2026-08-24 14:18 ` [PATCH 11/25] mm/fbatch: remove migration's PAGE_WAS_MLOCKED lru_add_drain() Hugh Dickins
2026-08-24 14:20 ` [PATCH 12/25] mm/fbatch: remove percpu_pvec_drained and folios_put() Hugh Dickins
2026-08-24 14:23 ` [PATCH 13/25] mm/fbatch: no lru_add_drain() to collect_longterm_unpinnable_folios() Hugh Dickins
2026-08-24 14:55 ` [PATCH alt " Hugh Dickins
2026-08-24 18:42 ` David Hildenbrand (Arm)
2026-08-27 9:16 ` Hugh Dickins
2026-08-27 9:20 ` David Hildenbrand (Arm)
2026-08-24 14:25 ` [PATCH 14/25] mm/fbatch: no lru_add_drain() nor _all() for memfd_wait_for_pins() Hugh Dickins
2026-08-24 14:27 ` [PATCH 15/25] mm/fbatch: remove shake_folio() shake_page() from memory-failure Hugh Dickins
2026-08-24 14:30 ` [PATCH 16/25] mm/fbatch: remove lru_cache_disable(() from NUMA folio migration Hugh Dickins
2026-08-24 14:32 ` [PATCH 17/25] mm/fbatch: no lru_cache_disable() in __alloc_contig_migrate_range() Hugh Dickins
2026-08-24 14:34 ` [PATCH 18/25] mm/fbatch: remove lru_add_drain() and _all() calls from various Hugh Dickins
2026-08-24 14:36 ` [PATCH 19/25] mm/fbatch: vm/stat_refresh include lru_add_drain() on each cpu Hugh Dickins
2026-08-24 14:39 ` [PATCH 20/25] s390/fbatch: no lru_add_drain_all() in s390_wiggle_split_folio() Hugh Dickins
2026-08-26 13:57 ` Claudio Imbrenda
2026-08-27 8:49 ` Hugh Dickins
2026-08-27 12:55 ` Claudio Imbrenda
2026-08-27 20:26 ` David Hildenbrand (Arm)
2026-08-28 8:57 ` Hugh Dickins
2026-08-28 15:02 ` Claudio Imbrenda
2026-08-28 22:02 ` Hugh Dickins
2026-08-24 14:41 ` [PATCH 21/25] block/fbatch: no lru_add_drain_all() in invalidate_bdev() Hugh Dickins
2026-08-24 14:44 ` [PATCH 22/25] fs/fbatch: drop_caches invalidate_bh_lrus() not lru_add_drain_all() Hugh Dickins
2026-08-24 14:47 ` [PATCH 23/25] fs,mm/fbatch: use invalidate_bh_lrus() not invalidate_bh_lrus_cpu() Hugh Dickins
2026-08-24 14:49 ` [PATCH 24/25] fs,mm/fbatch: lru_cache_disable() keep off buffer_head lrus only Hugh Dickins
2026-08-24 14:51 ` [PATCH 25/25] mm/fbatch: move lru_add_drain_all() declaration to mm/internal.h Hugh Dickins
2026-08-27 17:16 ` [PATCH 00/25] mm/fbatch: drain lru_add_drain() and _all() David Hildenbrand (Arm)
2026-09-02 3:54 ` [PATCH 26/25] mm/fbatch: drop reference inside the loop when draining Hugh Dickins
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=aplHq9bvNdyPGEw-@thinkstation \
--to=kas@kernel.org \
--cc=ackerleytng@google.com \
--cc=akpm@linux-foundation.org \
--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=hughd@google.com \
--cc=imbrenda@linux.ibm.com \
--cc=jack@suse.cz \
--cc=jp.kobryn@linux.dev \
--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.