@@ -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