ipv6: avoid taking locks at socket dismantle
authorEric Dumazet <edumazet@google.com>
Wed, 5 Dec 2012 09:18:10 +0000 (09:18 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 5 Dec 2012 21:01:28 +0000 (16:01 -0500)
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>
net/ipv6/anycast.c
net/ipv6/mcast.c

index 2f4f584d796dd3f27a7c580621bea4035ea1728f..757a810d8f15a5270bbcdf1f734768371d892e73 100644 (file)
@@ -189,6 +189,9 @@ void ipv6_sock_ac_close(struct sock *sk)
        struct net *net = sock_net(sk);
        int     prev_index;
 
+       if (!np->ipv6_ac_list)
+               return;
+
        write_lock_bh(&ipv6_sk_ac_lock);
        pac = np->ipv6_ac_list;
        np->ipv6_ac_list = NULL;
index b19ed51a45bbe1e42a4405902bedfd2b4bdd49dc..28dfa5f3801febb37cfd4ab17e010be4cc936e24 100644 (file)
@@ -284,6 +284,9 @@ void ipv6_sock_mc_close(struct sock *sk)
        struct ipv6_mc_socklist *mc_lst;
        struct net *net = sock_net(sk);
 
+       if (!rcu_access_pointer(np->ipv6_mc_list))
+               return;
+
        spin_lock(&ipv6_sk_mc_lock);
        while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list,
                                lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) {