mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: dhowells@redhat.com
Cc: netdev@vger.kernel.org, marc.dionne@auristor.com,
	kuba@kernel.org, davem@davemloft.net, edumazet@google.com,
	pabeni@redhat.com, horms@kernel.org,
	linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org,
	nicoyip.dev@gmail.com, stable@vger.kernel.org
Subject: Re: [PATCH net v9 09/14] rxrpc: Fix generation of notifications after call completion
Date: Tue, 08 Sep 2026 20:49:45 +0000	[thread overview]
Message-ID: <178890058557.219967.11776960278332769876@kernel.org> (raw)
In-Reply-To: <20260907113743.1453210-10-dhowells@redhat.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider:

Critical: 0 · High: 0 · Medium: 0 · Low: 2

- [Low] Undisclosed behavioural divergence introduced by the refactor:
  the new helper rxrpc_requeue_call() (net/rxrpc/recvmsg.c:22-46), which…
- [Low] Comment vs code mismatch in net/rxrpc/call_state.c: the new
  wrapper rxrpc_notify_socket() (line 54) carries a comment that is a…

--

rxrpc: Fix generation of notifications after call completion

The patch stops AF_RXRPC from generating a second notification after a call
has completed by splitting rxrpc_notify_socket() into a skip-if-completed
wrapper plus an unconditional __rxrpc_notify_socket() in call_state.c.  The
recvmsg path instead gets a new lightweight rxrpc_requeue_call() helper that
only puts the call back on rx->recvmsg_q.

A couple of questions below about the split.

> diff --git a/net/rxrpc/call_state.c b/net/rxrpc/call_state.c
> index 6afb54373ebbf..364810c652766 100644
> --- a/net/rxrpc/call_state.c
> +++ b/net/rxrpc/call_state.c
> @@ -7,6 +7,60 @@
>  
>  #include "ar-internal.h"
>  
> +/*
> + * Post a call for attention by the socket or kernel service.
> + */
> +static void __rxrpc_notify_socket(struct rxrpc_call *call)
> +{
> +	struct rxrpc_sock *rx;
> +	struct sock *sk;
> +	unsigned long flags;
> +
> +	if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
> +		rxrpc_see_call(call, rxrpc_call_see_notify_released);
> +		return;
> +	}
> +
> +	rcu_read_lock();
> +
> +	rx = rcu_dereference(call->socket);
> +	sk = &rx->sk;
> +	if (rx && sk->sk_state < RXRPC_CLOSE) {
> +		if (call->notify_rx) {
> +			spin_lock_irqsave(&call->notify_lock, flags);
> +			call->notify_rx(sk, call, call->user_call_ID);
> +			spin_unlock_irqrestore(&call->notify_lock, flags);
> +		} else {
> +			spin_lock_irqsave(&rx->recvmsg_lock, flags);
> +			if (list_empty(&call->recvmsg_link)) {
> +				rxrpc_get_call(call, rxrpc_call_get_notify_socket);
> +				list_add_tail(&call->recvmsg_link, &rx->recvmsg_q);
> +			}
> +			spin_unlock_irqrestore(&rx->recvmsg_lock, flags);
> +
> +			if (!sock_flag(sk, SOCK_DEAD)) {
> +				_debug("call %ps", sk->sk_data_ready);
> +				sk->sk_data_ready(sk);
> +			}
> +		}
> +	}
> +
> +	rcu_read_unlock();
> +}
> +
> +/*
> + * Post a call for attention by the socket or kernel service.
> + */
> +void rxrpc_notify_socket(struct rxrpc_call *call)
> +{
> +	if (rxrpc_call_is_complete(call)) {
> +		rxrpc_see_call(call, rxrpc_call_see_notify_skipped);
> +		return;
> +	}
> +
> +	__rxrpc_notify_socket(call);
> +}

[Severity: Low]
This isn't a bug, but the comment on the new rxrpc_notify_socket() wrapper is
a verbatim copy of the one on __rxrpc_notify_socket(), and the wrapper does
not post anything when rxrpc_call_is_complete(call) is true, it just emits
the rxrpc_call_see_notify_skipped trace and returns.

Since the skip is the only difference between the two functions, and is the
reason rxrpc_set_call_completion() must use the double-underscore variant,
would it be worth mentioning it in the comment?  As it stands, a caller that
needs a completed-but-not-yet-drained call re-posted cannot tell from the
comments which variant to pick.

> diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
> index 56fa324d0962e..28b2148b56936 100644
> --- a/net/rxrpc/recvmsg.c
> +++ b/net/rxrpc/recvmsg.c
> @@ -17,14 +17,12 @@
>  #include "ar-internal.h"
>  
>  /*
> - * Post a call for attention by the socket or kernel service.  Further
> - * notifications are suppressed by putting recvmsg_link on a dummy queue.
> + * Requeue a call for recvmsg() to pick up.
>   */
> -void rxrpc_notify_socket(struct rxrpc_call *call)
> +static void rxrpc_requeue_call(struct socket *sock, struct rxrpc_call *call)
>  {
> -	struct rxrpc_sock *rx;
> -	struct sock *sk;
> -	unsigned long flags;
> +	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
> +	struct sock *sk = &rx->sk;
>  
>  	_enter("%d", call->debug_id);
>  
> @@ -33,31 +31,18 @@ void rxrpc_notify_socket(struct rxrpc_call *call)
>  		return;
>  	}
>  
> -	rcu_read_lock();
> -
> -	rx = rcu_dereference(call->socket);
> -	sk = &rx->sk;
> -	if (rx && sk->sk_state < RXRPC_CLOSE) {
> -		if (call->notify_rx) {
> -			spin_lock_irqsave(&call->notify_lock, flags);
> -			call->notify_rx(sk, call, call->user_call_ID);
> -			spin_unlock_irqrestore(&call->notify_lock, flags);
> -		} else {
> -			spin_lock_irqsave(&rx->recvmsg_lock, flags);
> -			if (list_empty(&call->recvmsg_link)) {
> -				rxrpc_get_call(call, rxrpc_call_get_notify_socket);
> -				list_add_tail(&call->recvmsg_link, &rx->recvmsg_q);
> -			}
> -			spin_unlock_irqrestore(&rx->recvmsg_lock, flags);
> +	spin_lock_irq(&rx->recvmsg_lock);
> +	if (list_empty(&call->recvmsg_link)) {
> +		rxrpc_get_call(call, rxrpc_call_get_notify_socket);
> +		list_add_tail(&call->recvmsg_link, &rx->recvmsg_q);
> +	}
> +	spin_unlock_irq(&rx->recvmsg_lock);

[Severity: Low]
Is dropping the "rx && sk->sk_state < RXRPC_CLOSE" test intentional here?

rxrpc_requeue_call() keeps only the RXRPC_CALL_RELEASED check, so it will add
the call to rx->recvmsg_q regardless of sk_state, while the other enqueue site
for the same list, __rxrpc_notify_socket() in call_state.c, still requires
sk_state < RXRPC_CLOSE.

The CLOSE transition looks like it was written as a fence for additions to
that list, since rxrpc_shutdown() and rxrpc_release_sock() in af_rxrpc.c set
it under the same lock:

net/rxrpc/af_rxrpc.c:rxrpc_shutdown() {
	...
	if (sk->sk_state < RXRPC_CLOSE) {
		spin_lock_irq(&rx->recvmsg_lock);
		sk->sk_state = RXRPC_CLOSE;
		sk->sk_shutdown = SHUTDOWN_MASK;
		spin_unlock_irq(&rx->recvmsg_lock);
	...
}

The requeue in rxrpc_recvmsg() runs after release_sock(&rx->sk), so a
concurrent shutdown(SHUT_RDWR) on another thread of the same socket can flip
sk_state to RXRPC_CLOSE in that window and the call is requeued anyway, with a
fresh rxrpc_call_get_notify_socket ref.

The consequences look bounded: the extra ref is reclaimed when
rxrpc_release_calls_on_socket() drains rx->recvmsg_q, and handing out
already-queued data after shutdown was possible before this patch too, since
rxrpc_recvmsg() has no RXRPC_CLOSE rejection and the fence never removes
entries that are already queued.

Similarly, the call->notify_rx branch is gone from this path.  That looks safe
today, since notify_rx is only set for kernel service calls and
__rxrpc_notify_socket() never puts those on rx->recvmsg_q, so every call
rxrpc_recvmsg() takes off that queue has notify_rx == NULL.

Would it be worth either restoring the sk_state test so both enqueue sites
agree, or noting in a comment why the requeue path does not need it?

> -			if (!sock_flag(sk, SOCK_DEAD)) {
> -				_debug("call %ps", sk->sk_data_ready);
> -				sk->sk_data_ready(sk);
> -			}
> -		}
> +	if (!sock_flag(sk, SOCK_DEAD)) {
> +		_debug("call %ps", sk->sk_data_ready);
> +		sk->sk_data_ready(sk);
>  	}
>  
> -	rcu_read_unlock();
>  	_leave("");
>  }

[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260907113743.1453210-1-dhowells%40redhat.com

  reply	other threads:[~2026-09-08 20:49 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-07 11:37 [PATCH net v9 00/14] rxrpc: Miscellaneous fixes David Howells
2026-09-07 11:37 ` [PATCH net v9 01/14] afs: Fix lack of loop around sendmsg() to rxrpc David Howells
2026-09-07 13:06   ` David Laight
2026-09-10 10:18   ` David Howells
2026-09-07 11:37 ` [PATCH net v9 02/14] afs: Fix afs to abort the rxrpc call on send error David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 03/14] rxrpc: Fix lack of loop around reply send in rxperf server David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 04/14] rxrpc: Fix sendmsg to not return an error if last packet queued David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 05/14] rxrpc: Fix sendmsg length David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 06/14] rxrpc: Fix packet encryption error handling David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 07/14] rxrpc: Fix update of call->tx_pending without holding lock David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 08/14] rxrpc: Fix double IRQ enablement David Howells
2026-09-07 11:37 ` [PATCH net v9 09/14] rxrpc: Fix generation of notifications after call completion David Howells
2026-09-08 20:49   ` netdev-bot+sashiko [this message]
2026-09-07 11:37 ` [PATCH net v9 10/14] rxrpc: Fix RxGK key parser to check enctype is supported David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 11/14] afs: Fix creation of RxGK CM channel token to have right size David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 12/14] afs: Fix lack of setting call->server when doing FS.InlineBulkStatus David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 13/14] rxrpc: fix use-after-free in rxrpc_poke_conn() David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 14/14] rxrpc: Take write lock when publishing the initial RxGK key David Howells
2026-09-08 20:49   ` netdev-bot+sashiko

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=178890058557.219967.11776960278332769876@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-afs@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.dionne@auristor.com \
    --cc=netdev@vger.kernel.org \
    --cc=nicoyip.dev@gmail.com \
    --cc=pabeni@redhat.com \
    --cc=stable@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®