* [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance
@ 2026-09-01 2:42 Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 01/12] user_namespace: Use acquire/release for nr_extents synchronization Jinjie Ruan
` (12 more replies)
0 siblings, 13 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Hi,
This series converts some existing smp_wmb()/smp_rmb() barrier pairs to
smp_store_release()/smp_load_acquire() across various subsystems.
Background
==========
Many architectures support load acquire and store release instructions
which can replace explicit memory barriers and save cycles. As noted
in the ARM architecture reference [1]:
"Weaker ordering requirements that are imposed by Load-Acquire and
Store-Release instructions allow for micro-architectural
optimizations, which could reduce some of the performance impacts
that are otherwise imposed by an explicit memory barrier.
If the ordering requirement is satisfied using either a Load-Acquire
or Store-Release, then it would be preferable to use these
instructions instead of a DMB."
On arm64, a typical seqcount [2] read loop requires 13 cycles with DMB
barriers. Replacing the read barrier with smp_load_acquire() reduces
this to 8 cycles on an Ampere Altra.
We also observed significant barrier overhead while profiling Unxibench
syscall test on arm64: a single getuid() call is ~8ns slower than on
a comparable x86 system, with the dominant cost in map_id_up()'s smp_rmb(),
which is a DMB ISHLD on arm64. Converting it to smp_load_acquire() allows
the use of LDAR, eliminating the measurable overhead.
This motivated a broader search for existing barrier pairs that can
be converted to the lighter acquire/release semantics.
Changes
=======
Each patch in this series targets a specific barrier pair where the
publish/subscribe pattern is already present:
- Writers populate data, then publish a flag/count/pointer via
smp_store_release()
- Readers load the flag/count/pointer via smp_load_acquire(), then
consume the data
This preserves the existing memory ordering guarantees while allowing
architectures with native acquire/release instructions (e.g. arm64's
STLR/LDAR) to avoid the cost of full one-way barriers (DMB ISHST/ISHLD).
On architectures without native support, the generated code is
generally no worse than the explicit barrier pair.
The conversions are mechanical and no functional change is intended.
Testing (arm64 Kunpeng HIP09 server)
================
1. UNIXBENCH syscall
Baseline: 715.27
Patched: 718.83
Improvement: +0.50%
2. fs/aio (fio + null_blk, 4 jobs):
Baseline: 1441k IOPS, 86.46us
Patched: 1452k IOPS, 85.80us
Improvement: ~0.8%
3. soreuseport (wrk, 8 servers):
Baseline: 162.6k req/s, 452.5us
Patched: 164.2k req/s, 449.4us
Improvement: ~1.0%
Both improvements are consistent across runs and align with the
expected savings from replacing DMB with LDAR/STLR on arm64.
[1]: https://support.arm.com/documentation/102336/0100/Load-Acquire-and-Store-Release-instructions
[2]: https://github.com/torvalds/linux/commit/d0dd066a0fa26d55c19ace9e89dedd9504c5bcba
Changes in v2:
- Fix pre-existing issue for ext4 and 8021q [3].
- Fix missing copy_mnt_idmap() udapte [3].
- Drop nacked isotp patch.
- Add test data.
- Add Reviewed-by and update fs patch as Jan suggested.
[3]: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
Jinjie Ruan (12):
user_namespace: Use acquire/release for nr_extents synchronization
lib/vsprintf: Use acquire/release for ptr_key publication
fs: aio: Use acquire/release for ring->tail publication
fs: Use acquire/release for fdtable resize synchronization
pidfs: Use test_bit_acquire() for attr flag tests
super: Use acquire for SB_BORN check in super_cache_count()
ext4: Fix out-of-bounds read in ext4_get_group_info()
ext4: Convert group-count barrier protocol to acquire/release
soreuseport: publish num_socks with acquire/release
net: sched: act_gact: use acquire/release for tcfg_ptype
8021q: Fix data race when publishing vlan net_device pointers
8021q: publish vlan_devices_arrays entries with acquire/release
fs/aio.c | 10 ++++------
fs/ext4/balloc.c | 2 +-
fs/ext4/ext4.h | 10 +++-------
fs/ext4/mballoc.c | 6 ++----
fs/ext4/resize.c | 19 +++++++++++--------
fs/file.c | 10 ++++------
fs/mnt_idmapping.c | 5 ++---
fs/pidfs.c | 6 ++----
fs/super.c | 6 ++----
kernel/user_namespace.c | 24 +++++++++++++-----------
lib/vsprintf.c | 11 ++++-------
net/8021q/vlan.c | 6 ++----
net/8021q/vlan.h | 12 +++++-------
net/core/sock_reuseport.c | 20 ++++++++------------
net/sched/act_gact.c | 12 ++++--------
15 files changed, 67 insertions(+), 92 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 01/12] user_namespace: Use acquire/release for nr_extents synchronization
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 02/12] lib/vsprintf: Use acquire/release for ptr_key publication Jinjie Ruan
` (11 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Replace smp_wmb()/smp_rmb() with smp_store_release()/smp_load_acquire()
when publishing and consuming `nr_extents`. This expresses the
publish/subscribe pattern more clearly and allows architectures with
native acquire/release instructions (e.g. arm64's STLR/LDAR) to avoid
the cost of full one-way barriers (DMB ISHST/ISHLD).
No functional change intended.
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Seth Forshee <sforshee@kernel.org>
Cc: Kees Cook <kees@kernel.org>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Assisted-by: DeepSeek:DeepSeek-V3
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
v2:
- Add missing load replace in copy_mnt_idmap()
---
fs/mnt_idmapping.c | 5 ++---
kernel/user_namespace.c | 24 +++++++++++++-----------
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/fs/mnt_idmapping.c b/fs/mnt_idmapping.c
index cb61fbdb52e9..612b266ab3da 100644
--- a/fs/mnt_idmapping.c
+++ b/fs/mnt_idmapping.c
@@ -219,10 +219,9 @@ EXPORT_SYMBOL_GPL(vfsgid_in_group_p);
static int copy_mnt_idmap(struct uid_gid_map *map_from,
struct uid_gid_map *map_to)
{
+ /* Pairs with smp_store_release() in map_write(). */
+ u32 nr_extents = smp_load_acquire(&map_from->nr_extents);
struct uid_gid_extent *forward, *reverse;
- u32 nr_extents = READ_ONCE(map_from->nr_extents);
- /* Pairs with smp_wmb() when writing the idmapping. */
- smp_rmb();
/*
* Don't blindly copy @map_to into @map_from if nr_extents is
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 0bed462e9b2a..576b667a8813 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -317,9 +317,9 @@ map_id_range_down_base(unsigned extents, struct uid_gid_map *map, u32 id, u32 co
static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
{
+ /* Pairs with smp_store_release() in map_write(). */
+ unsigned int extents = smp_load_acquire(&map->nr_extents);
struct uid_gid_extent *extent;
- unsigned extents = map->nr_extents;
- smp_rmb();
if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
extent = map_id_range_down_base(extents, map, id, count);
@@ -383,9 +383,9 @@ map_id_range_up_max(unsigned extents, struct uid_gid_map *map, u32 id, u32 count
u32 map_id_range_up(struct uid_gid_map *map, u32 id, u32 count)
{
+ /* Pairs with smp_store_release() in map_write(). */
+ unsigned int extents = smp_load_acquire(&map->nr_extents);
struct uid_gid_extent *extent;
- unsigned extents = map->nr_extents;
- smp_rmb();
if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
extent = map_id_range_up_base(extents, map, id, count);
@@ -676,9 +676,9 @@ static int projid_m_show(struct seq_file *seq, void *v)
static void *m_start(struct seq_file *seq, loff_t *ppos,
struct uid_gid_map *map)
{
+ /* Pairs with smp_store_release() in map_write(). */
+ unsigned int extents = smp_load_acquire(&map->nr_extents);
loff_t pos = *ppos;
- unsigned extents = map->nr_extents;
- smp_rmb();
if (pos >= extents)
return NULL;
@@ -967,9 +967,11 @@ static ssize_t map_write(struct file *file, const char __user *buf,
* desired behavior is to see the values of the extents that
* were written before the count of the extents.
*
- * To achieve this smp_wmb() is used on guarantee the write
- * order and smp_rmb() is guaranteed that we don't have crazy
- * architectures returning stale data.
+ * The nr_extents field is the publish point for the extent
+ * data. Writers use smp_store_release() to ensure all extent
+ * data is visible before nr_extents is updated. Readers use
+ * smp_load_acquire() to ensure they see a consistent view of
+ * the extent data when reading nr_extents.
*/
mutex_lock(&userns_state_mutex);
@@ -1098,8 +1100,8 @@ static ssize_t map_write(struct file *file, const char __user *buf,
map->forward = new_map.forward;
map->reverse = new_map.reverse;
}
- smp_wmb();
- map->nr_extents = new_map.nr_extents;
+ /* Pairs with smp_load_acquire() in map_id_range_{up,down}() and m_start(). */
+ smp_store_release(&map->nr_extents, new_map.nr_extents);
*ppos = count;
ret = count;
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 02/12] lib/vsprintf: Use acquire/release for ptr_key publication
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 01/12] user_namespace: Use acquire/release for nr_extents synchronization Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 03/12] fs: aio: Use acquire/release for ring->tail publication Jinjie Ruan
` (10 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Replace the smp_wmb() + WRITE_ONCE() and READ_ONCE() + smp_rmb() barrier
pair with smp_store_release()/smp_load_acquire() on filled_random_ptr_key.
This expresses the publish/subscribe pattern more clearly and allows
architectures with native acquire/release instructions (e.g. arm64's
STLR/LDAR) to avoid the cost of full one-way barriers (DMB ISHST/ISHLD).
No functional change intended.
Cc: Petr Mladek <pmladek@suse.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Assisted-by: DeepSeek:DeepSeek-V3
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
lib/vsprintf.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 1d95ab9314bf..90d0a724eadd 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -762,9 +762,8 @@ static int fill_ptr_key(struct notifier_block *nb, unsigned long action, void *d
{
get_random_bytes(&ptr_key, sizeof(ptr_key));
- /* Pairs with smp_rmb() before reading ptr_key. */
- smp_wmb();
- WRITE_ONCE(filled_random_ptr_key, true);
+ /* Pairs with smp_load_acquire() before reading ptr_key. */
+ smp_store_release(&filled_random_ptr_key, true);
return NOTIFY_DONE;
}
@@ -781,12 +780,10 @@ static inline int __ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
{
unsigned long hashval;
- if (!READ_ONCE(filled_random_ptr_key))
+ /* Pairs with smp_store_release() after writing ptr_key. */
+ if (!smp_load_acquire(&filled_random_ptr_key))
return -EBUSY;
- /* Pairs with smp_wmb() after writing ptr_key. */
- smp_rmb();
-
#ifdef CONFIG_64BIT
hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 03/12] fs: aio: Use acquire/release for ring->tail publication
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 01/12] user_namespace: Use acquire/release for nr_extents synchronization Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 02/12] lib/vsprintf: Use acquire/release for ptr_key publication Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 04/12] fs: Use acquire/release for fdtable resize synchronization Jinjie Ruan
` (9 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Replace the smp_wmb() + WRITE_ONCE(ring->tail) and READ_ONCE(ring->tail)
+ smp_rmb() barrier pair with smp_store_release()/smp_load_acquire()
on `ring->tail`.
This expresses the publish/subscribe pattern more clearly and allows
architectures with native acquire/release instructions (e.g. arm64's
STLR/LDAR) to avoid the cost of full one-way barriers (DMB ISHST/ISHLD).
The release ensures event data written before updating ring->tail is
visible to readers that observe the new tail value via acquire, which
is exactly the ordering the barrier pair provided.
No functional change intended.
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Assisted-by: DeepSeek:DeepSeek-V3
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
fs/aio.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/aio.c b/fs/aio.c
index d78acc69f487..a0279e059e97 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1206,13 +1206,12 @@ static void aio_complete(struct aio_kiocb *iocb)
/* after flagging the request as done, we
* must never even look at it again
*/
- smp_wmb(); /* make event visible before updating tail */
-
ctx->tail = tail;
ring = folio_address(ctx->ring_folios[0]);
head = ring->head;
- ring->tail = tail;
+ /* Make event visible before updating tail */
+ smp_store_release(&ring->tail, tail);
flush_dcache_folio(ctx->ring_folios[0]);
ctx->completed_events++;
@@ -1288,13 +1287,12 @@ static long aio_read_events_ring(struct kioctx *ctx,
/* Access to ->ring_folios here is protected by ctx->ring_lock. */
ring = folio_address(ctx->ring_folios[0]);
head = ring->head;
- tail = ring->tail;
-
/*
* Ensure that once we've read the current tail pointer, that
* we also see the events that were stored up to the tail.
+ * Pairs with smp_store_release() in aio_complete().
*/
- smp_rmb();
+ tail = smp_load_acquire(&ring->tail);
pr_debug("h%u t%u m%u\n", head, tail, ctx->nr_events);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 04/12] fs: Use acquire/release for fdtable resize synchronization
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (2 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 03/12] fs: aio: Use acquire/release for ring->tail publication Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 05/12] pidfs: Use test_bit_acquire() for attr flag tests Jinjie Ruan
` (8 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Replace the smp_wmb()/smp_rmb() barrier pair with
smp_store_release()/smp_load_acquire() on `files->resize_in_progress`.
The flag is the publish point for fdtable expansion: writers clear it
via release after rcu_assign_pointer(), readers check it via acquire
before rcu_dereference_sched(). Observing it clear guarantees the new
fdt pointer is visible.
This expresses the pattern more clearly and allows cheaper one-way
barriers on weakly-ordered architectures (e.g. arm64 STLR/LDAR vs
DMB ISHST/ISHLD).
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Reviewed-by: Jan Kara <jack@suse.cz>
Assisted-by: DeepSeek:DeepSeek-V3
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
fs/file.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/file.c b/fs/file.c
index 628ca07dc4b1..86c035d459f2 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -273,8 +273,6 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
rcu_assign_pointer(files->fdt, new_fdt);
if (cur_fdt != &files->fdtab)
call_rcu(&cur_fdt->rcu, free_fdtable_rcu);
- /* coupled with smp_rmb() in fd_install() */
- smp_wmb();
return 0;
}
@@ -313,7 +311,8 @@ static int expand_files(struct files_struct *files, unsigned int nr)
/* All good, so we try */
files->resize_in_progress = true;
error = expand_fdtable(files, nr);
- files->resize_in_progress = false;
+ /* coupled with smp_load_acquire() in fd_install() */
+ smp_store_release(&files->resize_in_progress, false);
wake_up_all(&files->resize_wait);
return error;
@@ -685,13 +684,12 @@ void fd_install(unsigned int fd, struct file *file)
return;
rcu_read_lock_sched();
- if (unlikely(files->resize_in_progress)) {
+ /* coupled with smp_store_release() in expand_files() */
+ if (unlikely(smp_load_acquire(&files->resize_in_progress))) {
rcu_read_unlock_sched();
fd_install_slowpath(fd, file);
return;
}
- /* coupled with smp_wmb() in expand_fdtable() */
- smp_rmb();
fdt = rcu_dereference_sched(files->fdt);
VFS_BUG_ON(rcu_access_pointer(fdt->fd[fd]) != NULL);
rcu_assign_pointer(fdt->fd[fd], file);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 05/12] pidfs: Use test_bit_acquire() for attr flag tests
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (3 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 04/12] fs: Use acquire/release for fdtable resize synchronization Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 06/12] super: Use acquire for SB_BORN check in super_cache_count() Jinjie Ruan
` (7 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Replace test_bit() + smp_rmb() with test_bit_acquire() for
PIDFS_ATTR_BIT_EXIT and PIDFS_ATTR_BIT_COREDUMP tests in pidfd_info().
The acquire semantics ensure that if the flag is observed set, the
associated attr fields written before smp_wmb() + set_bit() are
also visible.
Writers keep smp_wmb() + set_bit() since no release bitop exists.
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Assisted-by: DeepSeek:DeepSeek-V3
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
fs/pidfs.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/fs/pidfs.c b/fs/pidfs.c
index a6a643f15d08..2cd0fab73180 100644
--- a/fs/pidfs.c
+++ b/fs/pidfs.c
@@ -393,8 +393,7 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
attr = READ_ONCE(pid->attr);
if (mask & PIDFD_INFO_EXIT) {
- if (test_bit(PIDFS_ATTR_BIT_EXIT, &attr->attr_mask)) {
- smp_rmb();
+ if (test_bit_acquire(PIDFS_ATTR_BIT_EXIT, &attr->attr_mask)) {
kinfo.mask |= PIDFD_INFO_EXIT;
#ifdef CONFIG_CGROUPS
kinfo.cgroupid = attr->cgroupid;
@@ -405,8 +404,7 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
}
if (mask & PIDFD_INFO_COREDUMP) {
- if (test_bit(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask)) {
- smp_rmb();
+ if (test_bit_acquire(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask)) {
kinfo.mask |= PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUMP_SIGNAL | PIDFD_INFO_COREDUMP_CODE;
kinfo.coredump_mask = attr->coredump_mask;
kinfo.coredump_signal = attr->coredump_signal;
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 06/12] super: Use acquire for SB_BORN check in super_cache_count()
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (4 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 05/12] pidfs: Use test_bit_acquire() for attr flag tests Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 07/12] ext4: Fix out-of-bounds read in ext4_get_group_info() Jinjie Ruan
` (6 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
The active SB_BORN check in super_cache_count() pairs with the
smp_store_release() in super_wake() when publishing a newly initialized
superblock.
Replace the historical independent smp_rmb() barrier with an acquire load
on sb->s_flags via super_flags(). This expresses the publish-subscribe
pattern more clearly and allows weakly-ordered architectures like arm64
to utilize efficient native instructions (e.g., LDAR) instead of a full
one-way barrier.
Also remove the outdated memory barrier comment in super_cache_count(),
as the underlying super_flags() implementation already self-documents
the matched smp_store_release() in super_wake().
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Assisted-by: Gemini:Gemini-3.1
Assisted-by: DeepSeek:DeepSeek-V3
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
fs/super.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/fs/super.c b/fs/super.c
index 05e443173038..caa6189e4057 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -267,12 +267,10 @@ static unsigned long super_cache_count(struct shrinker *shrink,
* However, if we are currently mounting the superblock, the underlying
* filesystem might be in a state of partial construction and hence it
* is dangerous to access it. super_trylock_shared() uses a SB_BORN check
- * to avoid this situation, so do the same here. The memory barrier is
- * matched with the one in mount_fs() as we don't hold locks here.
+ * to avoid this situation, so do the same here.
*/
- if (!(sb->s_flags & SB_BORN))
+ if (!super_flags(sb, SB_BORN))
return 0;
- smp_rmb();
if (sb->s_op && sb->s_op->nr_cached_objects &&
super_fs_objects_eligible(sc))
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 07/12] ext4: Fix out-of-bounds read in ext4_get_group_info()
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (5 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 06/12] super: Use acquire for SB_BORN check in super_cache_count() Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 6:44 ` Zhang Yi
2026-09-01 13:55 ` Jan Kara
2026-09-01 2:42 ` [PATCH v2 08/12] ext4: Convert group-count barrier protocol to acquire/release Jinjie Ruan
` (5 subsequent siblings)
12 siblings, 2 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
A plain read of s_groups_count in ext4_get_group_info() allows CPU
load-load reordering. On weak memory models, speculative prefetch of
s_group_info prior to the boundary check could lead to an out-of-bounds
read if a concurrent online resize expands the array and increments
s_groups_count.
The data race occurs between the ioctl configuration path (holding the
resize lock via ext4_resize_begin) and the lockless metadata lookup path:
CPU 0 (Writer, Resize Lock) CPU 1 (Reader, Lockless)
--------------------------- ------------------------
ext4_ioctl()
[EXT4_IOC_GROUP_ADD]
ext4_ioctl_group_add()
ext4_resize_begin() // Takes lock
ext4_group_add()
ext4_mb_alloc_groupinfo()
// Publishes expanded array via RCU
rcu_assign_pointer(s_group_info, ...)
ext4_flex_group_add()
ext4_update_super()
ext4_get_group_info()
// Speculative / out-of-order read
[Loads old/smaller s_group_info pointer]
[Plain C store / smp_wmb()]
sbi->s_groups_count += ...;
// Reads new s_groups_count,
// boundary check passes
if (group >= s_groups_count)
// Out-of-bounds array access!
sbi_array_rcu_deref(..., s_group_info)
Fix this by using ext4_get_groups_count() to enforce acquire semantics.
Cc: stable@vger.kernel.org
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: Baokun Li <libaokun@linux.alibaba.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Cc: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
Cc: Zhang Yi <yi.zhang@huawei.com>
Fixes: 5354b2af3406 ("ext4: allow ext4_get_group_info() to fail")
Link: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
fs/ext4/balloc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 52f4c5169f91..778fe8788f06 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -329,7 +329,7 @@ struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
struct ext4_group_info **grp_info;
long indexv, indexh;
- if (unlikely(group >= EXT4_SB(sb)->s_groups_count))
+ if (unlikely(group >= ext4_get_groups_count(sb)))
return NULL;
if (unlikely(!EXT4_SB(sb)->s_group_info))
return NULL;
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 08/12] ext4: Convert group-count barrier protocol to acquire/release
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (6 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 07/12] ext4: Fix out-of-bounds read in ext4_get_group_info() Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 09/12] soreuseport: publish num_socks with acquire/release Jinjie Ruan
` (4 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
During an online resize, reading s_groups_count and s_blockfile_groups
requires strict ordering against subsequent initialized block group
metadata.
Replace the historical smp_wmb()/smp_rmb() pairs with smp_store_release()
and smp_load_acquire(). This formalizes the publish-subscribe pattern
and allows weakly-ordered architectures (e.g., arm64) to utilize native
STLR/LDAR instructions instead of full DMB fences.
Update the documentation in resize.c and ext4.h accordingly.
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: Baokun Li <libaokun@linux.alibaba.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Cc: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
Cc: Zhang Yi <yi.zhang@huawei.com>
Assisted-by: Gemini:Gemini-3.1
Assisted-by: DeepSeek:DeepSeek-V3
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
fs/ext4/ext4.h | 10 +++-------
fs/ext4/mballoc.c | 6 ++----
fs/ext4/resize.c | 19 +++++++++++--------
3 files changed, 16 insertions(+), 19 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 724a27e8be61..d70b9cb09155 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3542,16 +3542,12 @@ static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size)
}
/*
- * Reading s_groups_count requires using smp_rmb() afterwards. See
- * the locking protocol documented in the comments of ext4_group_add()
- * in resize.c
+ * Reading s_groups_count uses acquire semantics.
*/
static inline ext4_group_t ext4_get_groups_count(struct super_block *sb)
{
- ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
-
- smp_rmb();
- return ngroups;
+ /* Pairs with smp_store_release() in ext4_update_super() */
+ return smp_load_acquire(&EXT4_SB(sb)->s_groups_count);
}
static inline ext4_group_t ext4_flex_group(struct ext4_sb_info *sbi,
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 06171a11db12..a15285224cdf 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -899,10 +899,8 @@ static ext4_group_t ext4_get_allocation_groups_count(
/* non-extent files are limited to low blocks/groups */
if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)))
- ngroups = EXT4_SB(ac->ac_sb)->s_blockfile_groups;
-
- /* Pairs with smp_wmb() in ext4_update_super() */
- smp_rmb();
+ /* Pairs with smp_store_release() in ext4_update_super() */
+ ngroups = smp_load_acquire(&EXT4_SB(ac->ac_sb)->s_blockfile_groups);
return ngroups;
}
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 2c5b851c552a..5e3ad8393cf8 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -1462,11 +1462,11 @@ static void ext4_update_super(struct super_block *sb,
*
* The precise rules we use are:
*
- * * Writers must perform a smp_wmb() after updating all
- * dependent data and before modifying the groups count
+ * * Writers must use a release store when updating the groups count
+ * after all dependent data has been updated
*
- * * Readers must perform an smp_rmb() after reading the groups
- * count and before reading any dependent data.
+ * * Readers must use an acquire load when reading the groups
+ * count before reading any dependent data.
*
* NB. These rules can be relaxed when checking the group count
* while freeing data, as we can only allocate from a block
@@ -1474,12 +1474,15 @@ static void ext4_update_super(struct super_block *sb,
* only then free after serialising in turn against that
* allocation.
*/
- smp_wmb();
/* Update the global fs size fields */
- sbi->s_groups_count += flex_gd->count;
- sbi->s_blockfile_groups = min(sbi->s_groups_count,
- (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
+ /* Pairs with smp_load_acquire() in ext4_get_groups_count() */
+ smp_store_release(&sbi->s_groups_count,
+ sbi->s_groups_count + flex_gd->count);
+ /* Pairs with smp_load_acquire() in ext4_get_allocation_groups_count() */
+ smp_store_release(&sbi->s_blockfile_groups,
+ min(sbi->s_groups_count,
+ (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb))));
/* Update the reserved block counts only once the new group is
* active. */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 09/12] soreuseport: publish num_socks with acquire/release
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (7 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 08/12] ext4: Convert group-count barrier protocol to acquire/release Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 10/12] net: sched: act_gact: use acquire/release for tcfg_ptype Jinjie Ruan
` (3 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Replace the smp_wmb()/smp_rmb() barrier pair with
smp_store_release()/smp_load_acquire() on reuse->num_socks.
Writers publish socks[] updates via release before incrementing
or decrementing the count; readers acquire the count before
accessing socks[], ensuring they observe a consistent view.
The detach path gains proper ordering between the socks[] write and
the decrement, which was previously unordered.
No functional change intended.
Cc: Eric Dumazet <edumazet@google.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Simon Horman <horms@kernel.org>
Assisted-by: DeepSeek:DeepSeek-V3
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
net/core/sock_reuseport.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
index 29948cb44b7d..6d3c511d1def 100644
--- a/net/core/sock_reuseport.c
+++ b/net/core/sock_reuseport.c
@@ -125,9 +125,8 @@ static void __reuseport_add_sock(struct sock *sk,
struct sock_reuseport *reuse)
{
reuse->socks[reuse->num_socks] = sk;
- /* paired with smp_rmb() in reuseport_(select|migrate)_sock() */
- smp_wmb();
- reuse->num_socks++;
+ /* paired with smp_load_acquire() in reuseport_(select|migrate)_sock() */
+ smp_store_release(&reuse->num_socks, reuse->num_socks + 1);
reuseport_get_incoming_cpu(sk, reuse);
}
@@ -140,7 +139,8 @@ static bool __reuseport_detach_sock(struct sock *sk,
return false;
reuse->socks[i] = reuse->socks[reuse->num_socks - 1];
- reuse->num_socks--;
+ /* paired with smp_load_acquire() in reuseport_(select|migrate)_sock() */
+ smp_store_release(&reuse->num_socks, reuse->num_socks - 1);
reuseport_put_incoming_cpu(sk, reuse);
return true;
@@ -583,11 +583,9 @@ struct sock *reuseport_select_sock(struct sock *sk,
goto out;
prog = rcu_dereference(reuse->prog);
- socks = READ_ONCE(reuse->num_socks);
+ /* paired with smp_store_release() in __reuseport_add_sock() */
+ socks = smp_load_acquire(&reuse->num_socks);
if (likely(socks)) {
- /* paired with smp_wmb() in __reuseport_add_sock() */
- smp_rmb();
-
if (!prog || !skb)
goto select_by_hash;
@@ -634,13 +632,11 @@ struct sock *reuseport_migrate_sock(struct sock *sk,
if (!reuse)
goto out;
- socks = READ_ONCE(reuse->num_socks);
+ /* paired with smp_store_release() in __reuseport_add_sock() */
+ socks = smp_load_acquire(&reuse->num_socks);
if (unlikely(!socks))
goto failure;
- /* paired with smp_wmb() in __reuseport_add_sock() */
- smp_rmb();
-
hash = migrating_sk->sk_hash;
prog = rcu_dereference(reuse->prog);
if (!prog || prog->expected_attach_type != BPF_SK_REUSEPORT_SELECT_OR_MIGRATE) {
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 10/12] net: sched: act_gact: use acquire/release for tcfg_ptype
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (8 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 09/12] soreuseport: publish num_socks with acquire/release Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 11/12] 8021q: Fix data race when publishing vlan net_device pointers Jinjie Ruan
` (2 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Replace the smp_wmb()/smp_rmb() barrier pair with
smp_store_release()/smp_load_acquire() on gact->tcfg_ptype.
tcf_gact_init() publishes tcfg_ptype via release after writing
tcfg_pval/tcfg_paction; tcf_gact_act() acquires it before
dispatching to gact_net_rand()/gact_determ(), ensuring the probability
parameters are visible.
No functional change intended.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@resnulli.us>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Assisted-by: DeepSeek:DeepSeek-V3
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
net/sched/act_gact.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 565860cccba6..d4f39f98e2cf 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -25,7 +25,6 @@ static struct tc_action_ops act_gact_ops;
#ifdef CONFIG_GACT_PROB
static int gact_net_rand(struct tcf_gact *gact)
{
- smp_rmb(); /* coupled with smp_wmb() in tcf_gact_init() */
if (get_random_u32_below(gact->tcfg_pval))
return gact->tcf_action;
return gact->tcfg_paction;
@@ -35,7 +34,6 @@ static int gact_determ(struct tcf_gact *gact)
{
u32 pack = atomic_inc_return(&gact->packets);
- smp_rmb(); /* coupled with smp_wmb() in tcf_gact_init() */
if (pack % gact->tcfg_pval)
return gact->tcf_action;
return gact->tcfg_paction;
@@ -133,11 +131,8 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
if (p_parm) {
gact->tcfg_paction = p_parm->paction;
gact->tcfg_pval = max_t(u16, 1, p_parm->pval);
- /* Make sure tcfg_pval is written before tcfg_ptype
- * coupled with smp_rmb() in gact_net_rand() & gact_determ()
- */
- smp_wmb();
- gact->tcfg_ptype = p_parm->ptype;
+ /* Pairs with smp_load_acquire() in tcf_gact_act(). */
+ smp_store_release(&gact->tcfg_ptype, p_parm->ptype);
}
#endif
spin_unlock_bh(&gact->tcf_lock);
@@ -160,7 +155,8 @@ TC_INDIRECT_SCOPE int tcf_gact_act(struct sk_buff *skb,
#ifdef CONFIG_GACT_PROB
{
- u32 ptype = READ_ONCE(gact->tcfg_ptype);
+ /* Pairs with smp_store_release() in tcf_gact_init() */
+ u32 ptype = smp_load_acquire(&gact->tcfg_ptype);
if (ptype)
action = gact_rand[ptype](gact);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 11/12] 8021q: Fix data race when publishing vlan net_device pointers
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (9 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 10/12] net: sched: act_gact: use acquire/release for tcfg_ptype Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 14:58 ` Jakub Kicinski
2026-09-01 2:42 ` [PATCH v2 12/12] 8021q: publish vlan_devices_arrays entries with acquire/release Jinjie Ruan
2026-09-01 3:06 ` [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Kuniyuki Iwashima
12 siblings, 1 reply; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
A plain C read and assignment of the net_device pointer
in the vlan_devices_arrays leaf entries lack proper atomicity
and ordering barriers. A concurrent lockless reader on the packet
receive fast-path could observe a torn or partially initialized
net_device pointer, leading to a potential out-of-bounds read or kernel
panic.
The data race occurs between the netlink/ioctl configuration paths
(holding the per-netns rtnl_nets_lock or RTNL lock) and the softirq
receive fast-path (holding rcu_read_lock()):
CPU 0 (Writer, rtnl_nets_lock/RTNL) CPU 1 (Reader, rcu_read_lock())
----------------------------------- -------------------------------
rtnetlink_rcv_msg()
// RTM_NEWLINK handler with RTNL_FLAG_DOIT_PERNET
rtnl_newlink()
ops->newlink() == vlan_newlink()
OR
vlan_ioctl_handler()
[ADD_VLAN_CMD] -> register_vlan_device()
register_vlan_dev()
vlan_group_set_device()
netif_receive_skb_core()
vlan_do_receive()
vlan_find_dev()
__vlan_group_get_device()
// Speculative / torn read
[Loads bad net_device *]
[Plain C store]
array[vlan_id] = dev;
// Dereferences bad pointer
// during device status check
vlan_dev->flags (PANIC!)
Fix this by using rcu_assign_pointer() in vlan_group_set_device()
and rcu_dereference_raw() in __vlan_group_get_device() to enforce
proper ordering and memory atomicity for the leaf entry traversal.
Cc: stable@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Stanislav Fomichev <sdf@fomichev.me>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Nicolai Buchwitz <nb@tipi-net.de>
Cc: Dan Aloni <da-x@monatomic.org>
Cc: Jeff Garzik <jeff@garzik.org>
Fixes: 5c15bdec5c38 ("[VLAN]: Avoid a 4-order allocation.")
Link: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
net/8021q/vlan.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index c41caaf94095..8030d616cb16 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -62,7 +62,7 @@ static inline struct net_device *__vlan_group_get_device(struct vlan_group *vg,
/* paired with smp_wmb() in vlan_group_prealloc_vid() */
smp_rmb();
- return array ? array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] : NULL;
+ return array ? rcu_dereference_raw(array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN]) : NULL;
}
static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
@@ -88,7 +88,7 @@ static inline void vlan_group_set_device(struct vlan_group *vg,
return;
array = vg->vlan_devices_arrays[pidx]
[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
- array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev;
+ rcu_assign_pointer(array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN], dev);
}
/* Must be invoked with rcu_read_lock or with RTNL. */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 12/12] 8021q: publish vlan_devices_arrays entries with acquire/release
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (10 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 11/12] 8021q: Fix data race when publishing vlan net_device pointers Jinjie Ruan
@ 2026-09-01 2:42 ` Jinjie Ruan
2026-09-01 3:06 ` [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Kuniyuki Iwashima
12 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 2:42 UTC (permalink / raw)
To: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, ruanjinjie, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel,
linux-aio, linux-kernel, linux-ext4, netdev
Replace the smp_wmb()/smp_rmb() barrier pair with
smp_store_release()/smp_load_acquire() on
vg->vlan_devices_arrays[pidx][vidx].
vlan_group_prealloc_vid() publishes the array pointer via release;
__vlan_group_get_device() acquires it before accessing the array,
ensuring the allocated entries are visible.
No functional change intended.
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Nicolai Buchwitz <nb@tipi-net.de>
Cc: Stanislav Fomichev <sdf@fomichev.me>
Cc: Hangbin Liu <liuhangbin@gmail.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Assisted-by: DeepSeek:DeepSeek-V3
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
net/8021q/vlan.c | 6 ++----
net/8021q/vlan.h | 8 +++-----
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 2d2efb877975..e34ada0cceac 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -70,10 +70,8 @@ static int vlan_group_prealloc_vid(struct vlan_group *vg,
if (array == NULL)
return -ENOBUFS;
- /* paired with smp_rmb() in __vlan_group_get_device() */
- smp_wmb();
-
- vg->vlan_devices_arrays[pidx][vidx] = array;
+ /* paired with smp_load_acquire() in __vlan_group_get_device() */
+ smp_store_release(&vg->vlan_devices_arrays[pidx][vidx], array);
return 0;
}
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 8030d616cb16..ee22637aa7ba 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -56,11 +56,9 @@ static inline struct net_device *__vlan_group_get_device(struct vlan_group *vg,
{
struct net_device **array;
- array = vg->vlan_devices_arrays[pidx]
- [vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
-
- /* paired with smp_wmb() in vlan_group_prealloc_vid() */
- smp_rmb();
+ /* Pairs with smp_store_release() in vlan_group_prealloc_vid() */
+ array = smp_load_acquire(&vg->vlan_devices_arrays[pidx]
+ [vlan_id / VLAN_GROUP_ARRAY_PART_LEN]);
return array ? rcu_dereference_raw(array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN]) : NULL;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
` (11 preceding siblings ...)
2026-09-01 2:42 ` [PATCH v2 12/12] 8021q: publish vlan_devices_arrays entries with acquire/release Jinjie Ruan
@ 2026-09-01 3:06 ` Kuniyuki Iwashima
2026-09-01 3:15 ` Jinjie Ruan
12 siblings, 1 reply; 18+ messages in thread
From: Kuniyuki Iwashima @ 2026-09-01 3:06 UTC (permalink / raw)
To: Jinjie Ruan
Cc: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, willemb, jhs, jiri, kees, cyphar, tglx, sdf,
nb, liuhangbin, da-x, jeff, linux-fsdevel, linux-aio,
linux-kernel, linux-ext4, netdev
On Mon, Aug 31, 2026 at 7:42 PM Jinjie Ruan <ruanjinjie@huawei.com> wrote:
>
> Hi,
>
> This series converts some existing smp_wmb()/smp_rmb() barrier pairs to
> smp_store_release()/smp_load_acquire() across various subsystems.
>
> Background
> ==========
>
> Many architectures support load acquire and store release instructions
> which can replace explicit memory barriers and save cycles. As noted
> in the ARM architecture reference [1]:
>
> "Weaker ordering requirements that are imposed by Load-Acquire and
> Store-Release instructions allow for micro-architectural
> optimizations, which could reduce some of the performance impacts
> that are otherwise imposed by an explicit memory barrier.
>
> If the ordering requirement is satisfied using either a Load-Acquire
> or Store-Release, then it would be preferable to use these
> instructions instead of a DMB."
>
> On arm64, a typical seqcount [2] read loop requires 13 cycles with DMB
> barriers. Replacing the read barrier with smp_load_acquire() reduces
> this to 8 cycles on an Ampere Altra.
>
> We also observed significant barrier overhead while profiling Unxibench
> syscall test on arm64: a single getuid() call is ~8ns slower than on
> a comparable x86 system, with the dominant cost in map_id_up()'s smp_rmb(),
> which is a DMB ISHLD on arm64. Converting it to smp_load_acquire() allows
> the use of LDAR, eliminating the measurable overhead.
>
> This motivated a broader search for existing barrier pairs that can
> be converted to the lighter acquire/release semantics.
>
> Changes
> =======
>
> Each patch in this series targets a specific barrier pair where the
> publish/subscribe pattern is already present:
>
> - Writers populate data, then publish a flag/count/pointer via
> smp_store_release()
>
> - Readers load the flag/count/pointer via smp_load_acquire(), then
> consume the data
>
> This preserves the existing memory ordering guarantees while allowing
> architectures with native acquire/release instructions (e.g. arm64's
> STLR/LDAR) to avoid the cost of full one-way barriers (DMB ISHST/ISHLD).
> On architectures without native support, the generated code is
> generally no worse than the explicit barrier pair.
>
> The conversions are mechanical and no functional change is intended.
>
> Testing (arm64 Kunpeng HIP09 server)
> ================
>
> 1. UNIXBENCH syscall
> Baseline: 715.27
> Patched: 718.83
> Improvement: +0.50%
>
> 2. fs/aio (fio + null_blk, 4 jobs):
> Baseline: 1441k IOPS, 86.46us
> Patched: 1452k IOPS, 85.80us
> Improvement: ~0.8%
>
> 3. soreuseport (wrk, 8 servers):
> Baseline: 162.6k req/s, 452.5us
> Patched: 164.2k req/s, 449.4us
> Improvement: ~1.0%
>
> Both improvements are consistent across runs and align with the
> expected savings from replacing DMB with LDAR/STLR on arm64.
>
> [1]: https://support.arm.com/documentation/102336/0100/Load-Acquire-and-Store-Release-instructions
> [2]: https://github.com/torvalds/linux/commit/d0dd066a0fa26d55c19ace9e89dedd9504c5bcba
>
> Changes in v2:
> - Fix pre-existing issue for ext4 and 8021q [3].
> - Fix missing copy_mnt_idmap() udapte [3].
> - Drop nacked isotp patch.
> - Add test data.
> - Add Reviewed-by and update fs patch as Jan suggested.
>
> [3]: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
>
> Jinjie Ruan (12):
> user_namespace: Use acquire/release for nr_extents synchronization
> lib/vsprintf: Use acquire/release for ptr_key publication
> fs: aio: Use acquire/release for ring->tail publication
> fs: Use acquire/release for fdtable resize synchronization
> pidfs: Use test_bit_acquire() for attr flag tests
> super: Use acquire for SB_BORN check in super_cache_count()
> ext4: Fix out-of-bounds read in ext4_get_group_info()
> ext4: Convert group-count barrier protocol to acquire/release
> soreuseport: publish num_socks with acquire/release
> net: sched: act_gact: use acquire/release for tcfg_ptype
> 8021q: Fix data race when publishing vlan net_device pointers
> 8021q: publish vlan_devices_arrays entries with acquire/release
Please post networking patches separately with the target tree specified:
Subject: [PATCH vX net-next] soreuseport: ...
8021q changes can be posted a series.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance
2026-09-01 3:06 ` [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Kuniyuki Iwashima
@ 2026-09-01 3:15 ` Jinjie Ruan
0 siblings, 0 replies; 18+ messages in thread
From: Jinjie Ruan @ 2026-09-01 3:15 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, willemb, jhs, jiri, kees, cyphar, tglx, sdf,
nb, liuhangbin, da-x, jeff, linux-fsdevel, linux-aio,
linux-kernel, linux-ext4, netdev
在 2026/9/1 11:06, Kuniyuki Iwashima 写道:
> On Mon, Aug 31, 2026 at 7:42 PM Jinjie Ruan <ruanjinjie@huawei.com> wrote:
>>
>> Hi,
>>
>> This series converts some existing smp_wmb()/smp_rmb() barrier pairs to
>> smp_store_release()/smp_load_acquire() across various subsystems.
>>
>> Background
>> ==========
>>
>> Many architectures support load acquire and store release instructions
>> which can replace explicit memory barriers and save cycles. As noted
>> in the ARM architecture reference [1]:
>>
>> "Weaker ordering requirements that are imposed by Load-Acquire and
>> Store-Release instructions allow for micro-architectural
>> optimizations, which could reduce some of the performance impacts
>> that are otherwise imposed by an explicit memory barrier.
>>
>> If the ordering requirement is satisfied using either a Load-Acquire
>> or Store-Release, then it would be preferable to use these
>> instructions instead of a DMB."
>>
>> On arm64, a typical seqcount [2] read loop requires 13 cycles with DMB
>> barriers. Replacing the read barrier with smp_load_acquire() reduces
>> this to 8 cycles on an Ampere Altra.
>>
>> We also observed significant barrier overhead while profiling Unxibench
>> syscall test on arm64: a single getuid() call is ~8ns slower than on
>> a comparable x86 system, with the dominant cost in map_id_up()'s smp_rmb(),
>> which is a DMB ISHLD on arm64. Converting it to smp_load_acquire() allows
>> the use of LDAR, eliminating the measurable overhead.
>>
>> This motivated a broader search for existing barrier pairs that can
>> be converted to the lighter acquire/release semantics.
>>
>> Changes
>> =======
>>
>> Each patch in this series targets a specific barrier pair where the
>> publish/subscribe pattern is already present:
>>
>> - Writers populate data, then publish a flag/count/pointer via
>> smp_store_release()
>>
>> - Readers load the flag/count/pointer via smp_load_acquire(), then
>> consume the data
>>
>> This preserves the existing memory ordering guarantees while allowing
>> architectures with native acquire/release instructions (e.g. arm64's
>> STLR/LDAR) to avoid the cost of full one-way barriers (DMB ISHST/ISHLD).
>> On architectures without native support, the generated code is
>> generally no worse than the explicit barrier pair.
>>
>> The conversions are mechanical and no functional change is intended.
>>
>> Testing (arm64 Kunpeng HIP09 server)
>> ================
>>
>> 1. UNIXBENCH syscall
>> Baseline: 715.27
>> Patched: 718.83
>> Improvement: +0.50%
>>
>> 2. fs/aio (fio + null_blk, 4 jobs):
>> Baseline: 1441k IOPS, 86.46us
>> Patched: 1452k IOPS, 85.80us
>> Improvement: ~0.8%
>>
>> 3. soreuseport (wrk, 8 servers):
>> Baseline: 162.6k req/s, 452.5us
>> Patched: 164.2k req/s, 449.4us
>> Improvement: ~1.0%
>>
>> Both improvements are consistent across runs and align with the
>> expected savings from replacing DMB with LDAR/STLR on arm64.
>>
>> [1]: https://support.arm.com/documentation/102336/0100/Load-Acquire-and-Store-Release-instructions
>> [2]: https://github.com/torvalds/linux/commit/d0dd066a0fa26d55c19ace9e89dedd9504c5bcba
>>
>> Changes in v2:
>> - Fix pre-existing issue for ext4 and 8021q [3].
>> - Fix missing copy_mnt_idmap() udapte [3].
>> - Drop nacked isotp patch.
>> - Add test data.
>> - Add Reviewed-by and update fs patch as Jan suggested.
>>
>> [3]: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
>>
>> Jinjie Ruan (12):
>> user_namespace: Use acquire/release for nr_extents synchronization
>> lib/vsprintf: Use acquire/release for ptr_key publication
>> fs: aio: Use acquire/release for ring->tail publication
>> fs: Use acquire/release for fdtable resize synchronization
>> pidfs: Use test_bit_acquire() for attr flag tests
>> super: Use acquire for SB_BORN check in super_cache_count()
>> ext4: Fix out-of-bounds read in ext4_get_group_info()
>> ext4: Convert group-count barrier protocol to acquire/release
>> soreuseport: publish num_socks with acquire/release
>> net: sched: act_gact: use acquire/release for tcfg_ptype
>> 8021q: Fix data race when publishing vlan net_device pointers
>> 8021q: publish vlan_devices_arrays entries with acquire/release
>
> Please post networking patches separately with the target tree specified:
>
> Subject: [PATCH vX net-next] soreuseport: ...
>
> 8021q changes can be posted a series.
Thanks for the review. I will split the series as suggested — the
networking patches will be posted separately.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 07/12] ext4: Fix out-of-bounds read in ext4_get_group_info()
2026-09-01 2:42 ` [PATCH v2 07/12] ext4: Fix out-of-bounds read in ext4_get_group_info() Jinjie Ruan
@ 2026-09-01 6:44 ` Zhang Yi
2026-09-01 13:55 ` Jan Kara
1 sibling, 0 replies; 18+ messages in thread
From: Zhang Yi @ 2026-09-01 6:44 UTC (permalink / raw)
To: Jinjie Ruan
Cc: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel, linux-aio,
linux-kernel, linux-ext4, netdev
On 9/1/2026 10:42 AM, Jinjie Ruan wrote:
> A plain read of s_groups_count in ext4_get_group_info() allows CPU
> load-load reordering. On weak memory models, speculative prefetch of
> s_group_info prior to the boundary check could lead to an out-of-bounds
> read if a concurrent online resize expands the array and increments
> s_groups_count.
>
> The data race occurs between the ioctl configuration path (holding the
> resize lock via ext4_resize_begin) and the lockless metadata lookup path:
>
> CPU 0 (Writer, Resize Lock) CPU 1 (Reader, Lockless)
> --------------------------- ------------------------
> ext4_ioctl()
> [EXT4_IOC_GROUP_ADD]
> ext4_ioctl_group_add()
> ext4_resize_begin() // Takes lock
> ext4_group_add()
> ext4_mb_alloc_groupinfo()
> // Publishes expanded array via RCU
> rcu_assign_pointer(s_group_info, ...)
>
> ext4_flex_group_add()
> ext4_update_super()
> ext4_get_group_info()
> // Speculative / out-of-order read
> [Loads old/smaller s_group_info pointer]
> [Plain C store / smp_wmb()]
> sbi->s_groups_count += ...;
> // Reads new s_groups_count,
> // boundary check passes
> if (group >= s_groups_count)
>
> // Out-of-bounds array access!
> sbi_array_rcu_deref(..., s_group_info)
>
> Fix this by using ext4_get_groups_count() to enforce acquire semantics.
>
> Cc: stable@vger.kernel.org
> Cc: "Theodore Ts'o" <tytso@mit.edu>
> Cc: Andreas Dilger <adilger.kernel@dilger.ca>
> Cc: Baokun Li <libaokun@linux.alibaba.com>
> Cc: Jan Kara <jack@suse.cz>
> Cc: Ojaswin Mujoo <ojaswin@linux.ibm.com>
> Cc: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
> Cc: Zhang Yi <yi.zhang@huawei.com>
> Fixes: 5354b2af3406 ("ext4: allow ext4_get_group_info() to fail")
> Link: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Looks good to me.
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
> ---
> fs/ext4/balloc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
> index 52f4c5169f91..778fe8788f06 100644
> --- a/fs/ext4/balloc.c
> +++ b/fs/ext4/balloc.c
> @@ -329,7 +329,7 @@ struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
> struct ext4_group_info **grp_info;
> long indexv, indexh;
>
> - if (unlikely(group >= EXT4_SB(sb)->s_groups_count))
> + if (unlikely(group >= ext4_get_groups_count(sb)))
> return NULL;
> if (unlikely(!EXT4_SB(sb)->s_group_info))
> return NULL;
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 07/12] ext4: Fix out-of-bounds read in ext4_get_group_info()
2026-09-01 2:42 ` [PATCH v2 07/12] ext4: Fix out-of-bounds read in ext4_get_group_info() Jinjie Ruan
2026-09-01 6:44 ` Zhang Yi
@ 2026-09-01 13:55 ` Jan Kara
1 sibling, 0 replies; 18+ messages in thread
From: Jan Kara @ 2026-09-01 13:55 UTC (permalink / raw)
To: Jinjie Ruan
Cc: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
kuba, pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar,
tglx, sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel, linux-aio,
linux-kernel, linux-ext4, netdev
On Tue 01-09-26 10:42:29, Jinjie Ruan wrote:
> A plain read of s_groups_count in ext4_get_group_info() allows CPU
> load-load reordering. On weak memory models, speculative prefetch of
> s_group_info prior to the boundary check could lead to an out-of-bounds
> read if a concurrent online resize expands the array and increments
> s_groups_count.
>
> The data race occurs between the ioctl configuration path (holding the
> resize lock via ext4_resize_begin) and the lockless metadata lookup path:
>
> CPU 0 (Writer, Resize Lock) CPU 1 (Reader, Lockless)
> --------------------------- ------------------------
> ext4_ioctl()
> [EXT4_IOC_GROUP_ADD]
> ext4_ioctl_group_add()
> ext4_resize_begin() // Takes lock
> ext4_group_add()
> ext4_mb_alloc_groupinfo()
> // Publishes expanded array via RCU
> rcu_assign_pointer(s_group_info, ...)
>
> ext4_flex_group_add()
> ext4_update_super()
> ext4_get_group_info()
> // Speculative / out-of-order read
> [Loads old/smaller s_group_info pointer]
> [Plain C store / smp_wmb()]
> sbi->s_groups_count += ...;
> // Reads new s_groups_count,
> // boundary check passes
> if (group >= s_groups_count)
>
> // Out-of-bounds array access!
> sbi_array_rcu_deref(..., s_group_info)
>
> Fix this by using ext4_get_groups_count() to enforce acquire semantics.
>
> Cc: stable@vger.kernel.org
> Cc: "Theodore Ts'o" <tytso@mit.edu>
> Cc: Andreas Dilger <adilger.kernel@dilger.ca>
> Cc: Baokun Li <libaokun@linux.alibaba.com>
> Cc: Jan Kara <jack@suse.cz>
> Cc: Ojaswin Mujoo <ojaswin@linux.ibm.com>
> Cc: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
> Cc: Zhang Yi <yi.zhang@huawei.com>
> Fixes: 5354b2af3406 ("ext4: allow ext4_get_group_info() to fail")
> Link: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/ext4/balloc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
> index 52f4c5169f91..778fe8788f06 100644
> --- a/fs/ext4/balloc.c
> +++ b/fs/ext4/balloc.c
> @@ -329,7 +329,7 @@ struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
> struct ext4_group_info **grp_info;
> long indexv, indexh;
>
> - if (unlikely(group >= EXT4_SB(sb)->s_groups_count))
> + if (unlikely(group >= ext4_get_groups_count(sb)))
> return NULL;
> if (unlikely(!EXT4_SB(sb)->s_group_info))
> return NULL;
> --
> 2.34.1
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 11/12] 8021q: Fix data race when publishing vlan net_device pointers
2026-09-01 2:42 ` [PATCH v2 11/12] 8021q: Fix data race when publishing vlan net_device pointers Jinjie Ruan
@ 2026-09-01 14:58 ` Jakub Kicinski
0 siblings, 0 replies; 18+ messages in thread
From: Jakub Kicinski @ 2026-09-01 14:58 UTC (permalink / raw)
To: Jinjie Ruan
Cc: viro, brauner, jack, bcrl, tytso, adilger.kernel, libaokun,
ojaswin, ritesh.list, yi.zhang, sforshee, pmladek, rostedt,
andriy.shevchenko, linux, senozhatsky, akpm, davem, edumazet,
pabeni, horms, kuniyu, willemb, jhs, jiri, kees, cyphar, tglx,
sdf, nb, liuhangbin, da-x, jeff, linux-fsdevel, linux-aio,
linux-kernel, linux-ext4, netdev
On Tue, 1 Sep 2026 10:42:33 +0800 Jinjie Ruan wrote:
> A plain C read and assignment of the net_device pointer
> in the vlan_devices_arrays leaf entries lack proper atomicity
> and ordering barriers. A concurrent lockless reader on the packet
> receive fast-path could observe a torn or partially initialized
> net_device pointer, leading to a potential out-of-bounds read or kernel
> panic.
>
> The data race occurs between the netlink/ioctl configuration paths
> (holding the per-netns rtnl_nets_lock or RTNL lock) and the softirq
> receive fast-path (holding rcu_read_lock()):
>
> CPU 0 (Writer, rtnl_nets_lock/RTNL) CPU 1 (Reader, rcu_read_lock())
> ----------------------------------- -------------------------------
> rtnetlink_rcv_msg()
> // RTM_NEWLINK handler with RTNL_FLAG_DOIT_PERNET
> rtnl_newlink()
> ops->newlink() == vlan_newlink()
> OR
> vlan_ioctl_handler()
> [ADD_VLAN_CMD] -> register_vlan_device()
>
> register_vlan_dev()
> vlan_group_set_device()
> netif_receive_skb_core()
> vlan_do_receive()
> vlan_find_dev()
> __vlan_group_get_device()
> // Speculative / torn read
> [Loads bad net_device *]
> [Plain C store]
> array[vlan_id] = dev;
> // Dereferences bad pointer
> // during device status check
> vlan_dev->flags (PANIC!)
>
> Fix this by using rcu_assign_pointer() in vlan_group_set_device()
> and rcu_dereference_raw() in __vlan_group_get_device() to enforce
> proper ordering and memory atomicity for the leaf entry traversal.
>
> Cc: stable@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Stanislav Fomichev <sdf@fomichev.me>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Nicolai Buchwitz <nb@tipi-net.de>
> Cc: Dan Aloni <da-x@monatomic.org>
> Cc: Jeff Garzik <jeff@garzik.org>
> Fixes: 5c15bdec5c38 ("[VLAN]: Avoid a 4-order allocation.")
> Link: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
make C=1 says:
net/8021q/vlan.c: note: in included file:
net/8021q/vlan.h:91:9: error: incompatible types in comparison expression (different address spaces):
net/8021q/vlan.h:91:9: struct net_device [noderef] __rcu *
net/8021q/vlan.h:91:9: struct net_device *
net/8021q/vlan.h:91:9: error: incompatible types in comparison expression (different address spaces):
net/8021q/vlan.h:91:9: struct net_device [noderef] __rcu *
net/8021q/vlan.h:91:9: struct net_device *
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-09-01 14:58 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01 2:42 [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 01/12] user_namespace: Use acquire/release for nr_extents synchronization Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 02/12] lib/vsprintf: Use acquire/release for ptr_key publication Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 03/12] fs: aio: Use acquire/release for ring->tail publication Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 04/12] fs: Use acquire/release for fdtable resize synchronization Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 05/12] pidfs: Use test_bit_acquire() for attr flag tests Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 06/12] super: Use acquire for SB_BORN check in super_cache_count() Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 07/12] ext4: Fix out-of-bounds read in ext4_get_group_info() Jinjie Ruan
2026-09-01 6:44 ` Zhang Yi
2026-09-01 13:55 ` Jan Kara
2026-09-01 2:42 ` [PATCH v2 08/12] ext4: Convert group-count barrier protocol to acquire/release Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 09/12] soreuseport: publish num_socks with acquire/release Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 10/12] net: sched: act_gact: use acquire/release for tcfg_ptype Jinjie Ruan
2026-09-01 2:42 ` [PATCH v2 11/12] 8021q: Fix data race when publishing vlan net_device pointers Jinjie Ruan
2026-09-01 14:58 ` Jakub Kicinski
2026-09-01 2:42 ` [PATCH v2 12/12] 8021q: publish vlan_devices_arrays entries with acquire/release Jinjie Ruan
2026-09-01 3:06 ` [PATCH v2 00/12] Convert barrier pairs to acquire/release for better performance Kuniyuki Iwashima
2026-09-01 3:15 ` Jinjie Ruan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox