@@ -98,7 +98,7 @@ static void netlink_skb_destructor(struct sk_buff *skb);
9898
9999/* nl_table locking explained:
100100 * Lookup and traversal are protected with an RCU read-side lock. Insertion
101- * and removal are protected with nl_sk_hash_lock while using RCU list
101+ * and removal are protected with per bucket lock while using RCU list
102102 * modification primitives and may run in parallel to RCU protected lookups.
103103 * Destruction of the Netlink socket may only occur *after* nl_table_lock has
104104 * been acquired * either during or after the socket has been removed from
@@ -110,10 +110,6 @@ static atomic_t nl_table_users = ATOMIC_INIT(0);
110110
111111#define nl_deref_protected (X ) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
112112
113- /* Protects netlink socket hash table mutations */
114- DEFINE_MUTEX (nl_sk_hash_lock );
115- EXPORT_SYMBOL_GPL (nl_sk_hash_lock );
116-
117113static ATOMIC_NOTIFIER_HEAD (netlink_chain );
118114
119115static DEFINE_SPINLOCK (netlink_tap_lock );
@@ -998,6 +994,19 @@ static struct sock *__netlink_lookup(struct netlink_table *table, u32 portid,
998994 & netlink_compare , & arg );
999995}
1000996
997+ static bool __netlink_insert (struct netlink_table * table , struct sock * sk ,
998+ struct net * net )
999+ {
1000+ struct netlink_compare_arg arg = {
1001+ .net = net ,
1002+ .portid = nlk_sk (sk )-> portid ,
1003+ };
1004+
1005+ return rhashtable_lookup_compare_insert (& table -> hash ,
1006+ & nlk_sk (sk )-> node ,
1007+ & netlink_compare , & arg );
1008+ }
1009+
10011010static struct sock * netlink_lookup (struct net * net , int protocol , u32 portid )
10021011{
10031012 struct netlink_table * table = & nl_table [protocol ];
@@ -1043,9 +1052,7 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
10431052 struct netlink_table * table = & nl_table [sk -> sk_protocol ];
10441053 int err = - EADDRINUSE ;
10451054
1046- mutex_lock (& nl_sk_hash_lock );
1047- if (__netlink_lookup (table , portid , net ))
1048- goto err ;
1055+ lock_sock (sk );
10491056
10501057 err = - EBUSY ;
10511058 if (nlk_sk (sk )-> portid )
@@ -1058,24 +1065,24 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
10581065
10591066 nlk_sk (sk )-> portid = portid ;
10601067 sock_hold (sk );
1061- rhashtable_insert (& table -> hash , & nlk_sk (sk )-> node );
1062- err = 0 ;
1068+ if (__netlink_insert (table , sk , net ))
1069+ err = 0 ;
1070+ else
1071+ sock_put (sk );
10631072err :
1064- mutex_unlock ( & nl_sk_hash_lock );
1073+ release_sock ( sk );
10651074 return err ;
10661075}
10671076
10681077static void netlink_remove (struct sock * sk )
10691078{
10701079 struct netlink_table * table ;
10711080
1072- mutex_lock (& nl_sk_hash_lock );
10731081 table = & nl_table [sk -> sk_protocol ];
10741082 if (rhashtable_remove (& table -> hash , & nlk_sk (sk )-> node )) {
10751083 WARN_ON (atomic_read (& sk -> sk_refcnt ) == 1 );
10761084 __sock_put (sk );
10771085 }
1078- mutex_unlock (& nl_sk_hash_lock );
10791086
10801087 netlink_table_grab ();
10811088 if (nlk_sk (sk )-> subscriptions ) {
0 commit comments