@@ -198,76 +198,48 @@ static inline int compute_score(struct sock *sk, struct net *net,
198198}
199199
200200/* 
201-  * Don't inline this cruft.  Here are some nice properties to exploit here. The 
202-  * BSD API  does not allow a listening sock to specify the remote port nor the 
201+  * Here are some nice properties to exploit here. The BSD API  
202+  * does not allow a listening sock to specify the remote port nor the 
203203 * remote address for the connection. So always assume those are both 
204204 * wildcarded during the search since they can never be otherwise. 
205205 */ 
206206
207- 
207+ /* called with rcu_read_lock() : No refcount taken on the socket */ 
208208struct  sock  * __inet_lookup_listener (struct  net  * net ,
209209				    struct  inet_hashinfo  * hashinfo ,
210210				    struct  sk_buff  * skb , int  doff ,
211211				    const  __be32  saddr , __be16  sport ,
212212				    const  __be32  daddr , const  unsigned short  hnum ,
213213				    const  int  dif )
214214{
215- 	struct  sock  * sk , * result ;
216- 	struct  hlist_nulls_node  * node ;
217215	unsigned int   hash  =  inet_lhashfn (net , hnum );
218216	struct  inet_listen_hashbucket  * ilb  =  & hashinfo -> listening_hash [hash ];
219- 	int  score , hiscore , matches  =  0 , reuseport  =  0 ;
220- 	bool   select_ok   =  true ;
217+ 	int  score , hiscore   =   0 , matches  =  0 , reuseport  =  0 ;
218+ 	struct   sock   * sk ,  * result   =   NULL ;
221219	u32  phash  =  0 ;
222220
223- begin :
224- 	result  =  NULL ;
225- 	hiscore  =  0 ;
226- 	sk_nulls_for_each_rcu (sk , node , & ilb -> head ) {
221+ 	sk_for_each_rcu (sk , & ilb -> head ) {
227222		score  =  compute_score (sk , net , hnum , daddr , dif );
228223		if  (score  >  hiscore ) {
229- 			result  =  sk ;
230- 			hiscore  =  score ;
231224			reuseport  =  sk -> sk_reuseport ;
232225			if  (reuseport ) {
233226				phash  =  inet_ehashfn (net , daddr , hnum ,
234227						     saddr , sport );
235- 				if  (select_ok ) {
236- 					struct  sock  * sk2 ;
237- 					sk2  =  reuseport_select_sock (sk , phash ,
238- 								    skb , doff );
239- 					if  (sk2 ) {
240- 						result  =  sk2 ;
241- 						goto found ;
242- 					}
243- 				}
228+ 				result  =  reuseport_select_sock (sk , phash ,
229+ 							       skb , doff );
230+ 				if  (result )
231+ 					return  result ;
244232				matches  =  1 ;
245233			}
234+ 			result  =  sk ;
235+ 			hiscore  =  score ;
246236		} else  if  (score  ==  hiscore  &&  reuseport ) {
247237			matches ++ ;
248238			if  (reciprocal_scale (phash , matches ) ==  0 )
249239				result  =  sk ;
250240			phash  =  next_pseudo_random32 (phash );
251241		}
252242	}
253- 	/* 
254- 	 * if the nulls value we got at the end of this lookup is 
255- 	 * not the expected one, we must restart lookup. 
256- 	 * We probably met an item that was moved to another chain. 
257- 	 */ 
258- 	if  (get_nulls_value (node ) !=  hash  +  LISTENING_NULLS_BASE )
259- 		goto begin ;
260- 	if  (result ) {
261- found :
262- 		if  (unlikely (!atomic_inc_not_zero (& result -> sk_refcnt )))
263- 			result  =  NULL ;
264- 		else  if  (unlikely (compute_score (result , net , hnum , daddr ,
265- 				  dif ) <  hiscore )) {
266- 			sock_put (result );
267- 			select_ok  =  false;
268- 			goto begin ;
269- 		}
270- 	}
271243	return  result ;
272244}
273245EXPORT_SYMBOL_GPL (__inet_lookup_listener );
@@ -508,7 +480,8 @@ int __inet_hash(struct sock *sk, struct sock *osk,
508480		if  (err )
509481			goto unlock ;
510482	}
511- 	__sk_nulls_add_node_rcu (sk , & ilb -> head );
483+ 	hlist_add_head_rcu (& sk -> sk_node , & ilb -> head );
484+ 	sock_set_flag (sk , SOCK_RCU_FREE );
512485	sock_prot_inuse_add (sock_net (sk ), sk -> sk_prot , 1 );
513486unlock :
514487	spin_unlock (& ilb -> lock );
@@ -535,20 +508,25 @@ void inet_unhash(struct sock *sk)
535508{
536509	struct  inet_hashinfo  * hashinfo  =  sk -> sk_prot -> h .hashinfo ;
537510	spinlock_t  * lock ;
511+ 	bool  listener  =  false;
538512	int  done ;
539513
540514	if  (sk_unhashed (sk ))
541515		return ;
542516
543- 	if  (sk -> sk_state  ==  TCP_LISTEN )
517+ 	if  (sk -> sk_state  ==  TCP_LISTEN ) { 
544518		lock  =  & hashinfo -> listening_hash [inet_sk_listen_hashfn (sk )].lock ;
545- 	else 
519+ 		listener  =  true;
520+ 	} else  {
546521		lock  =  inet_ehash_lockp (hashinfo , sk -> sk_hash );
547- 
522+ 	} 
548523	spin_lock_bh (lock );
549524	if  (rcu_access_pointer (sk -> sk_reuseport_cb ))
550525		reuseport_detach_sock (sk );
551- 	done  =  __sk_nulls_del_node_init_rcu (sk );
526+ 	if  (listener )
527+ 		done  =  __sk_del_node_init (sk );
528+ 	else 
529+ 		done  =  __sk_nulls_del_node_init_rcu (sk );
552530	if  (done )
553531		sock_prot_inuse_add (sock_net (sk ), sk -> sk_prot , -1 );
554532	spin_unlock_bh (lock );
@@ -684,9 +662,8 @@ void inet_hashinfo_init(struct inet_hashinfo *h)
684662
685663	for  (i  =  0 ; i  <  INET_LHTABLE_SIZE ; i ++ ) {
686664		spin_lock_init (& h -> listening_hash [i ].lock );
687- 		INIT_HLIST_NULLS_HEAD (& h -> listening_hash [i ].head ,
688- 				      i  +  LISTENING_NULLS_BASE );
689- 		}
665+ 		INIT_HLIST_HEAD (& h -> listening_hash [i ].head );
666+ 	}
690667}
691668EXPORT_SYMBOL_GPL (inet_hashinfo_init );
692669
0 commit comments