diff options
author | Eric Dumazet <edumazet@google.com> | 2023-09-22 05:42:17 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-10-01 20:39:18 +0200 |
commit | a4725d0d893599253a4bb283fdabdd4a66d9451d (patch) | |
tree | 4fd909c34741d50fa43a45780c342b6c183af4ac /net/ipv4/ip_sockglue.c | |
parent | inet: implement lockless IP_TOS (diff) | |
download | linux-a4725d0d893599253a4bb283fdabdd4a66d9451d.tar.xz linux-a4725d0d893599253a4bb283fdabdd4a66d9451d.zip |
inet: lockless getsockopt(IP_OPTIONS)
inet->inet_opt being RCU protected, we can use RCU instead
of locking the socket.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@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 | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 50c008efbb6d..45d89487914a 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -1591,27 +1591,20 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname, case IP_TOS: val = READ_ONCE(inet->tos); goto copyval; - } - - if (needs_rtnl) - rtnl_lock(); - sockopt_lock_sock(sk); - - switch (optname) { case IP_OPTIONS: { unsigned char optbuf[sizeof(struct ip_options)+40]; struct ip_options *opt = (struct ip_options *)optbuf; struct ip_options_rcu *inet_opt; - inet_opt = rcu_dereference_protected(inet->inet_opt, - lockdep_sock_is_held(sk)); + rcu_read_lock(); + inet_opt = rcu_dereference(inet->inet_opt); opt->optlen = 0; if (inet_opt) memcpy(optbuf, &inet_opt->opt, sizeof(struct ip_options) + inet_opt->opt.optlen); - sockopt_release_sock(sk); + rcu_read_unlock(); if (opt->optlen == 0) { len = 0; @@ -1627,6 +1620,13 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname, return -EFAULT; return 0; } + } + + if (needs_rtnl) + rtnl_lock(); + sockopt_lock_sock(sk); + + switch (optname) { case IP_MTU: { struct dst_entry *dst; |