diff options
author | Eric Dumazet <edumazet@google.com> | 2023-09-21 23:28:11 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-10-01 21:09:54 +0300 |
commit | 10bbf1652c1cca9819e98d56f3432c56d7a2d229 (patch) | |
tree | ab9494c905436ea6f2b9fa1bb979addd2d58da71 /net/core/sock.c | |
parent | 06bc3668cc2a6db2831b9086f0e3c6ebda599dba (diff) | |
download | linux-10bbf1652c1cca9819e98d56f3432c56d7a2d229.tar.xz |
net: implement lockless SO_PRIORITY
This is a followup of 8bf43be799d4 ("net: annotate data-races
around sk->sk_priority").
sk->sk_priority can be read and written without holding the socket lock.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index a5995750c5c5..1fdc0a0d8ff2 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -806,9 +806,7 @@ EXPORT_SYMBOL(sock_no_linger); void sock_set_priority(struct sock *sk, u32 priority) { - lock_sock(sk); WRITE_ONCE(sk->sk_priority, priority); - release_sock(sk); } EXPORT_SYMBOL(sock_set_priority); @@ -1118,6 +1116,18 @@ int sk_setsockopt(struct sock *sk, int level, int optname, valbool = val ? 1 : 0; + /* handle options which do not require locking the socket. */ + switch (optname) { + case SO_PRIORITY: + if ((val >= 0 && val <= 6) || + sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) || + sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) { + sock_set_priority(sk, val); + return 0; + } + return -EPERM; + } + sockopt_lock_sock(sk); switch (optname) { @@ -1213,15 +1223,6 @@ set_sndbuf: sk->sk_no_check_tx = valbool; break; - case SO_PRIORITY: - if ((val >= 0 && val <= 6) || - sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) || - sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) - WRITE_ONCE(sk->sk_priority, val); - else - ret = -EPERM; - break; - case SO_LINGER: if (optlen < sizeof(ling)) { ret = -EINVAL; /* 1003.1g */ |