[PATCH net-next v3] soreuseport: publish num_socks with acquire/release

Jinjie Ruan posted 1 patch 3 weeks, 3 days ago
net/core/sock_reuseport.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
[PATCH net-next v3] soreuseport: publish num_socks with acquire/release
Posted by Jinjie Ruan 3 weeks, 3 days ago
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>
---
v3:
- Split out from following patch set as Kuniyuki suggested.
Link: https://lore.kernel.org/all/20260901024234.135119-1-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
Re: [PATCH net-next v3] soreuseport: publish num_socks with acquire/release
Posted by Eric Dumazet 3 weeks, 3 days ago
On Wed, Sep 2, 2026 at 9:18 AM Jinjie Ruan <ruanjinjie@huawei.com> wrote:
>
> 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>
> ---
> v3:
> - Split out from following patch set as Kuniyuki suggested.
> Link: https://lore.kernel.org/all/20260901024234.135119-1-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];

OK, but I think we should fix these problematic accesses to reuse->socks[X]
to avoid load/store tearing before your patch?

This might avoid some KCSAN / AI-review reports.

Please squash the following parts (shown before your changes) into
your v4 patch:

I think that this could target the net tree, with
Fixes: ef456144da8e ("soreuseport: define reuseport groups")

Please wait ~24 hours before sending a V4.

Thanks.

diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
index 29948cb44b7d1a8864ff680aaeb2b4582ede5ff4..8380936fae736337b902f70f0f5ebc1155a3bf37
100644
--- a/net/core/sock_reuseport.c
+++ b/net/core/sock_reuseport.c
@@ -139,7 +139,7 @@ static bool __reuseport_detach_sock(struct sock *sk,
        if (i == -1)
                return false;

-       reuse->socks[i] = reuse->socks[reuse->num_socks - 1];
+       WRITE_ONCE(reuse->socks[i], reuse->socks[reuse->num_socks - 1]);
        reuse->num_socks--;
        reuseport_put_incoming_cpu(sk, reuse);

@@ -521,7 +521,7 @@ static struct sock *run_bpf_filter(struct
sock_reuseport *reuse, u16 socks,
        if (index >= socks)
                return NULL;

-       return reuse->socks[index];
+       return READ_ONCE(reuse->socks[index]);
 }

 static struct sock *reuseport_select_sock_by_hash(struct sock_reuseport *reuse,
@@ -532,7 +532,7 @@ static struct sock
*reuseport_select_sock_by_hash(struct sock_reuseport *reuse,

        i = j = reciprocal_scale(hash, num_socks);
        do {
-               struct sock *sk = reuse->socks[i];
+               struct sock *sk = READ_ONCE(reuse->socks[i]);

                if (sk->sk_state != TCP_ESTABLISHED) {
                        /* Paired with WRITE_ONCE() in
__reuseport_(get|put)_incoming_cpu(). */