ipv6: avoid taking locks at socket dismantle
ipv6_sock_mc_close() is called for ipv6 sockets at close time, and most of them don't use multicast. Add a test to avoid contention on a shared spinlock. Same heuristic applies for ipv6_sock_ac_close(), to avoid contention on a shared rwlock. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
cc86802805
commit
0e1efe9d5e
|
@ -189,6 +189,9 @@ void ipv6_sock_ac_close(struct sock *sk)
|
||||||
struct net *net = sock_net(sk);
|
struct net *net = sock_net(sk);
|
||||||
int prev_index;
|
int prev_index;
|
||||||
|
|
||||||
|
if (!np->ipv6_ac_list)
|
||||||
|
return;
|
||||||
|
|
||||||
write_lock_bh(&ipv6_sk_ac_lock);
|
write_lock_bh(&ipv6_sk_ac_lock);
|
||||||
pac = np->ipv6_ac_list;
|
pac = np->ipv6_ac_list;
|
||||||
np->ipv6_ac_list = NULL;
|
np->ipv6_ac_list = NULL;
|
||||||
|
|
|
@ -284,6 +284,9 @@ void ipv6_sock_mc_close(struct sock *sk)
|
||||||
struct ipv6_mc_socklist *mc_lst;
|
struct ipv6_mc_socklist *mc_lst;
|
||||||
struct net *net = sock_net(sk);
|
struct net *net = sock_net(sk);
|
||||||
|
|
||||||
|
if (!rcu_access_pointer(np->ipv6_mc_list))
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock(&ipv6_sk_mc_lock);
|
spin_lock(&ipv6_sk_mc_lock);
|
||||||
while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list,
|
while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list,
|
||||||
lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) {
|
lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) {
|
||||||
|
|
Loading…
Reference in a new issue