Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

af_unix: Don't use skb_recv_datagram() in unix_stream_read_skb().

unix_stream_read_skb() calls skb_recv_datagram() with MSG_DONTWAIT,
which is mostly equivalent to sock_error(sk) + skb_dequeue().

In the following patch, we will add a new field to cache the number
of bytes in the receive queue. Then, we want to avoid introducing
atomic ops in the fast path, so we will reuse the receive queue lock.

As a preparation for the change, let's not use skb_recv_datagram()
in unix_stream_read_skb().

Note that sock_error() is now moved out of the u->iolock mutex as
the mutex does not synchronise the peer's close() at all.

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250702223606.1054680-4-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kuniyuki Iwashima and committed by
Jakub Kicinski
d0aac854 772f0104

+22 -17
+22 -17
net/unix/af_unix.c
··· 2786 2786 2787 2787 static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) 2788 2788 { 2789 + struct sk_buff_head *queue = &sk->sk_receive_queue; 2789 2790 struct unix_sock *u = unix_sk(sk); 2790 2791 struct sk_buff *skb; 2791 2792 int err; ··· 2794 2793 if (unlikely(READ_ONCE(sk->sk_state) != TCP_ESTABLISHED)) 2795 2794 return -ENOTCONN; 2796 2795 2797 - mutex_lock(&u->iolock); 2798 - skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err); 2799 - mutex_unlock(&u->iolock); 2800 - if (!skb) 2796 + err = sock_error(sk); 2797 + if (err) 2801 2798 return err; 2802 2799 2800 + mutex_lock(&u->iolock); 2801 + spin_lock(&queue->lock); 2802 + 2803 + skb = __skb_dequeue(queue); 2804 + if (!skb) { 2805 + spin_unlock(&queue->lock); 2806 + mutex_unlock(&u->iolock); 2807 + return -EAGAIN; 2808 + } 2809 + 2803 2810 #if IS_ENABLED(CONFIG_AF_UNIX_OOB) 2804 - if (unlikely(skb == READ_ONCE(u->oob_skb))) { 2805 - bool drop = false; 2811 + if (skb == u->oob_skb) { 2812 + WRITE_ONCE(u->oob_skb, NULL); 2813 + spin_unlock(&queue->lock); 2814 + mutex_unlock(&u->iolock); 2806 2815 2807 - spin_lock(&sk->sk_receive_queue.lock); 2808 - if (likely(skb == u->oob_skb)) { 2809 - WRITE_ONCE(u->oob_skb, NULL); 2810 - drop = true; 2811 - } 2812 - spin_unlock(&sk->sk_receive_queue.lock); 2813 - 2814 - if (drop) { 2815 - kfree_skb_reason(skb, SKB_DROP_REASON_UNIX_SKIP_OOB); 2816 - return -EAGAIN; 2817 - } 2816 + kfree_skb_reason(skb, SKB_DROP_REASON_UNIX_SKIP_OOB); 2817 + return -EAGAIN; 2818 2818 } 2819 2819 #endif 2820 + 2821 + spin_unlock(&queue->lock); 2822 + mutex_unlock(&u->iolock); 2820 2823 2821 2824 return recv_actor(sk, skb); 2822 2825 }