Skip to content

Commit a54d51f

Browse files
edumazetdavem330
authored andcommitted
udp: fix busy polling
Generic sk_busy_loop_end() only looks at sk->sk_receive_queue for presence of packets. Problem is that for UDP sockets after blamed commit, some packets could be present in another queue: udp_sk(sk)->reader_queue In some cases, a busy poller could spin until timeout expiration, even if some packets are available in udp_sk(sk)->reader_queue. v3: - make sk_busy_loop_end() nicer (Willem) v2: - add a READ_ONCE(sk->sk_family) in sk_is_inet() to avoid KCSAN splats. - add a sk_is_inet() check in sk_is_udp() (Willem feedback) - add a sk_is_inet() check in sk_is_tcp(). Fixes: 2276f58 ("udp: use a separate rx queue for packet reception") Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Paolo Abeni <pabeni@redhat.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e3f9bed commit a54d51f

File tree

4 files changed

+26
-14
lines changed

4 files changed

+26
-14
lines changed

include/linux/skmsg.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,6 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock)
505505
return !!psock->saved_data_ready;
506506
}
507507

508-
static inline bool sk_is_udp(const struct sock *sk)
509-
{
510-
return sk->sk_type == SOCK_DGRAM &&
511-
sk->sk_protocol == IPPROTO_UDP;
512-
}
513-
514508
#if IS_ENABLED(CONFIG_NET_SOCK_MSG)
515509

516510
#define BPF_F_STRPARSER (1UL << 1)

include/net/inet_sock.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,6 @@ static inline unsigned long inet_cmsg_flags(const struct inet_sock *inet)
307307
#define inet_assign_bit(nr, sk, val) \
308308
assign_bit(INET_FLAGS_##nr, &inet_sk(sk)->inet_flags, val)
309309

310-
static inline bool sk_is_inet(struct sock *sk)
311-
{
312-
return sk->sk_family == AF_INET || sk->sk_family == AF_INET6;
313-
}
314-
315310
/**
316311
* sk_to_full_sk - Access to a full socket
317312
* @sk: pointer to a socket

include/net/sock.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2765,9 +2765,25 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags)
27652765
&skb_shinfo(skb)->tskey);
27662766
}
27672767

2768+
static inline bool sk_is_inet(const struct sock *sk)
2769+
{
2770+
int family = READ_ONCE(sk->sk_family);
2771+
2772+
return family == AF_INET || family == AF_INET6;
2773+
}
2774+
27682775
static inline bool sk_is_tcp(const struct sock *sk)
27692776
{
2770-
return sk->sk_type == SOCK_STREAM && sk->sk_protocol == IPPROTO_TCP;
2777+
return sk_is_inet(sk) &&
2778+
sk->sk_type == SOCK_STREAM &&
2779+
sk->sk_protocol == IPPROTO_TCP;
2780+
}
2781+
2782+
static inline bool sk_is_udp(const struct sock *sk)
2783+
{
2784+
return sk_is_inet(sk) &&
2785+
sk->sk_type == SOCK_DGRAM &&
2786+
sk->sk_protocol == IPPROTO_UDP;
27712787
}
27722788

27732789
static inline bool sk_is_stream_unix(const struct sock *sk)

net/core/sock.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
#include <linux/interrupt.h>
108108
#include <linux/poll.h>
109109
#include <linux/tcp.h>
110+
#include <linux/udp.h>
110111
#include <linux/init.h>
111112
#include <linux/highmem.h>
112113
#include <linux/user_namespace.h>
@@ -4144,8 +4145,14 @@ bool sk_busy_loop_end(void *p, unsigned long start_time)
41444145
{
41454146
struct sock *sk = p;
41464147

4147-
return !skb_queue_empty_lockless(&sk->sk_receive_queue) ||
4148-
sk_busy_loop_timeout(sk, start_time);
4148+
if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
4149+
return true;
4150+
4151+
if (sk_is_udp(sk) &&
4152+
!skb_queue_empty_lockless(&udp_sk(sk)->reader_queue))
4153+
return true;
4154+
4155+
return sk_busy_loop_timeout(sk, start_time);
41494156
}
41504157
EXPORT_SYMBOL(sk_busy_loop_end);
41514158
#endif /* CONFIG_NET_RX_BUSY_POLL */

0 commit comments

Comments
 (0)