Re: [PATCH net v1 1/2] af_unix: Fix inq_len update problem in partial read
From: Kuniyuki Iwashima <kuniyu@google.com>
Date: 2026-05-27 07:03:08
On Tue, May 26, 2026 at 11:54 PM [off-list ref] wrote:
quoted hunk ↗ jump to hunk
From: Jianyu Li <redacted> Currently inq_len is updated only when the whole skb is consumed. If only part of the data is read, following SIOCINQ query would get value greater than what actually left. This change update inq_len timely in unix_stream_read_generic(), and adjust unix_stream_read_skb() accordingly to prevent repetitive update. Fixes: f4e1fb04c123 ("af_unix: Use cached value for SOCK_STREAM in unix_inq_len().") Signed-off-by: Jianyu Li <redacted> --- net/unix/af_unix.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index dc71ed79b..2f0b73598 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c@@ -2886,7 +2886,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) return -EAGAIN; } - WRITE_ONCE(u->inq_len, u->inq_len - skb->len); + WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb)); #if IS_ENABLED(CONFIG_AF_UNIX_OOB) if (skb == u->oob_skb) {@@ -3056,6 +3056,10 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state, if (!(flags & MSG_PEEK)) { UNIXCB(skb).consumed += chunk; + spin_lock(&sk->sk_receive_queue.lock); + WRITE_ONCE(u->inq_len, u->inq_len - chunk); + spin_unlock(&sk->sk_receive_queue.lock); + sk_peek_offset_bwd(sk, chunk); if (UNIXCB(skb).fp) {@@ -3067,7 +3071,6 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state, break; spin_lock(&sk->sk_receive_queue.lock); - WRITE_ONCE(u->inq_len, u->inq_len - skb->len); __skb_unlink(skb, &sk->sk_receive_queue); spin_unlock(&sk->sk_receive_queue.lock);
Could you combine the two chunks above like this to avoid
locking dance ?
spin_lock(&sk->sk_receive_queue.lock);
WRITE_ONCE(u->inq_len, u->inq_len - chunk);
if (unix_skb_len(skb)) {
spin_unlock(&sk->sk_receive_queue.lock);
break;
}
__skb_unlink(skb, &sk->sk_receive_queue);
spin_unlock(&sk->sk_receive_queue.lock);
-- 2.45.2