diff options
author | Eric Dumazet <edumazet@google.com> | 2023-08-16 10:15:35 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-08-16 12:09:17 +0200 |
commit | 6b5f43ea08150e7ff72f734545101c58489ead5b (patch) | |
tree | 805b596ad9e4070ad6766a0e11b601d9a88edbac /net/ipv4/ip_sockglue.c | |
parent | inet: set/get simple options locklessly (diff) | |
download | linux-6b5f43ea08150e7ff72f734545101c58489ead5b.tar.xz linux-6b5f43ea08150e7ff72f734545101c58489ead5b.zip |
inet: move inet->recverr to inet->inet_flags
IP_RECVERR socket option can now be set/get without locking the socket.
This patch potentially avoid data-races around inet->recverr.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ip_sockglue.c')
-rw-r--r-- | net/ipv4/ip_sockglue.c | 23 |
1 files changed, 10 insertions, 13 deletions
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 69b87518348a..8283d862a9db 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -446,12 +446,11 @@ EXPORT_SYMBOL_GPL(ip_icmp_error); void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info) { - struct inet_sock *inet = inet_sk(sk); struct sock_exterr_skb *serr; struct iphdr *iph; struct sk_buff *skb; - if (!inet->recverr) + if (!inet_test_bit(RECVERR, sk)) return; skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC); @@ -617,9 +616,7 @@ EXPORT_SYMBOL(ip_sock_set_freebind); void ip_sock_set_recverr(struct sock *sk) { - lock_sock(sk); - inet_sk(sk)->recverr = true; - release_sock(sk); + inet_set_bit(RECVERR, sk); } EXPORT_SYMBOL(ip_sock_set_recverr); @@ -978,6 +975,11 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname, return -EINVAL; inet_assign_bit(RECVFRAGSIZE, sk, val); return 0; + case IP_RECVERR: + inet_assign_bit(RECVERR, sk, val); + if (!val) + skb_queue_purge(&sk->sk_error_queue); + return 0; } err = 0; @@ -1064,11 +1066,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname, goto e_inval; inet->pmtudisc = val; break; - case IP_RECVERR: - inet->recverr = !!val; - if (!val) - skb_queue_purge(&sk->sk_error_queue); - break; case IP_RECVERR_RFC4884: if (val < 0 || val > 1) goto e_inval; @@ -1575,6 +1572,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname, case IP_RECVFRAGSIZE: val = inet_test_bit(RECVFRAGSIZE, sk); goto copyval; + case IP_RECVERR: + val = inet_test_bit(RECVERR, sk); + goto copyval; } if (needs_rtnl) @@ -1649,9 +1649,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname, } break; } - case IP_RECVERR: - val = inet->recverr; - break; case IP_RECVERR_RFC4884: val = inet->recverr_rfc4884; break; |