aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/sock.c
diff options
context:
space:
mode:
authorEric Dumazet <[email protected]>2023-09-21 20:28:11 +0000
committerDavid S. Miller <[email protected]>2023-10-01 18:09:54 +0000
commit10bbf1652c1cca9819e98d56f3432c56d7a2d229 (patch)
treeab9494c905436ea6f2b9fa1bb979addd2d58da71 /net/core/sock.c
parentopenvswitch: reduce stack usage in do_execute_actions (diff)
downloadkernel-10bbf1652c1cca9819e98d56f3432c56d7a2d229.tar.gz
kernel-10bbf1652c1cca9819e98d56f3432c56d7a2d229.zip
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 <[email protected]> Reviewed-by: Wenjia Zhang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
Diffstat (limited to 'net/core/sock.c')
-rw-r--r--net/core/sock.c23
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 */