@@ -565,106 +565,106 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
565565 struct sock * , __u16 , struct inet_timewait_sock * * ))
566566{
567567 struct inet_hashinfo * hinfo = death_row -> hashinfo ;
568- const unsigned short snum = inet_sk ( sk ) -> inet_num ;
568+ struct inet_timewait_sock * tw = NULL ;
569569 struct inet_bind_hashbucket * head ;
570- struct inet_bind_bucket * tb ;
571- int ret ;
570+ int port = inet_sk (sk )-> inet_num ;
572571 struct net * net = sock_net (sk );
572+ struct inet_bind_bucket * tb ;
573+ u32 remaining , offset ;
574+ int ret , i , low , high ;
575+ static u32 hint ;
576+
577+ if (port ) {
578+ head = & hinfo -> bhash [inet_bhashfn (net , port ,
579+ hinfo -> bhash_size )];
580+ tb = inet_csk (sk )-> icsk_bind_hash ;
581+ spin_lock_bh (& head -> lock );
582+ if (sk_head (& tb -> owners ) == sk && !sk -> sk_bind_node .next ) {
583+ inet_ehash_nolisten (sk , NULL );
584+ spin_unlock_bh (& head -> lock );
585+ return 0 ;
586+ }
587+ spin_unlock (& head -> lock );
588+ /* No definite answer... Walk to established hash table */
589+ ret = check_established (death_row , sk , port , NULL );
590+ local_bh_enable ();
591+ return ret ;
592+ }
573593
574- if (! snum ) {
575- int i , remaining , low , high , port ;
576- static u32 hint ;
577- u32 offset = hint + port_offset ;
578- struct inet_timewait_sock * tw = NULL ;
594+ inet_get_local_port_range ( net , & low , & high );
595+ high ++ ; /* [32768, 60999] -> [32768, 61000[ */
596+ remaining = high - low ;
597+ if ( likely ( remaining > 1 ))
598+ remaining &= ~ 1U ;
579599
580- inet_get_local_port_range (net , & low , & high );
581- remaining = (high - low ) + 1 ;
600+ offset = (hint + port_offset ) % remaining ;
601+ /* In first pass we try ports of @low parity.
602+ * inet_csk_get_port() does the opposite choice.
603+ */
604+ offset &= ~1U ;
605+ other_parity_scan :
606+ port = low + offset ;
607+ for (i = 0 ; i < remaining ; i += 2 , port += 2 ) {
608+ if (unlikely (port >= high ))
609+ port -= remaining ;
610+ if (inet_is_local_reserved_port (net , port ))
611+ continue ;
612+ head = & hinfo -> bhash [inet_bhashfn (net , port ,
613+ hinfo -> bhash_size )];
614+ spin_lock_bh (& head -> lock );
582615
583- /* By starting with offset being an even number,
584- * we tend to leave about 50% of ports for other uses,
585- * like bind(0).
616+ /* Does not bother with rcv_saddr checks, because
617+ * the established check is already unique enough.
586618 */
587- offset &= ~1 ;
588-
589- local_bh_disable ();
590- for (i = 0 ; i < remaining ; i ++ ) {
591- port = low + (i + offset ) % remaining ;
592- if (inet_is_local_reserved_port (net , port ))
593- continue ;
594- head = & hinfo -> bhash [inet_bhashfn (net , port ,
595- hinfo -> bhash_size )];
596- spin_lock (& head -> lock );
597-
598- /* Does not bother with rcv_saddr checks,
599- * because the established check is already
600- * unique enough.
601- */
602- inet_bind_bucket_for_each (tb , & head -> chain ) {
603- if (net_eq (ib_net (tb ), net ) &&
604- tb -> port == port ) {
605- if (tb -> fastreuse >= 0 ||
606- tb -> fastreuseport >= 0 )
607- goto next_port ;
608- WARN_ON (hlist_empty (& tb -> owners ));
609- if (!check_established (death_row , sk ,
610- port , & tw ))
611- goto ok ;
619+ inet_bind_bucket_for_each (tb , & head -> chain ) {
620+ if (net_eq (ib_net (tb ), net ) && tb -> port == port ) {
621+ if (tb -> fastreuse >= 0 ||
622+ tb -> fastreuseport >= 0 )
612623 goto next_port ;
613- }
624+ WARN_ON (hlist_empty (& tb -> owners ));
625+ if (!check_established (death_row , sk ,
626+ port , & tw ))
627+ goto ok ;
628+ goto next_port ;
614629 }
615-
616- tb = inet_bind_bucket_create (hinfo -> bind_bucket_cachep ,
617- net , head , port );
618- if (!tb ) {
619- spin_unlock (& head -> lock );
620- break ;
621- }
622- tb -> fastreuse = -1 ;
623- tb -> fastreuseport = -1 ;
624- goto ok ;
625-
626- next_port :
627- spin_unlock (& head -> lock );
628630 }
629- local_bh_enable ();
630-
631- return - EADDRNOTAVAIL ;
632631
633- ok :
634- hint += (i + 2 ) & ~1 ;
635-
636- /* Head lock still held and bh's disabled */
637- inet_bind_hash (sk , tb , port );
638- if (sk_unhashed (sk )) {
639- inet_sk (sk )-> inet_sport = htons (port );
640- inet_ehash_nolisten (sk , (struct sock * )tw );
632+ tb = inet_bind_bucket_create (hinfo -> bind_bucket_cachep ,
633+ net , head , port );
634+ if (!tb ) {
635+ spin_unlock_bh (& head -> lock );
636+ return - ENOMEM ;
641637 }
642- if (tw )
643- inet_twsk_bind_unhash (tw , hinfo );
644- spin_unlock (& head -> lock );
638+ tb -> fastreuse = -1 ;
639+ tb -> fastreuseport = -1 ;
640+ goto ok ;
641+ next_port :
642+ spin_unlock_bh (& head -> lock );
643+ cond_resched ();
644+ }
645645
646- if (tw )
647- inet_twsk_deschedule_put (tw );
646+ offset ++ ;
647+ if ((offset & 1 ) && remaining > 1 )
648+ goto other_parity_scan ;
648649
649- ret = 0 ;
650- goto out ;
651- }
650+ return - EADDRNOTAVAIL ;
652651
653- head = & hinfo -> bhash [inet_bhashfn (net , snum , hinfo -> bhash_size )];
654- tb = inet_csk (sk )-> icsk_bind_hash ;
655- spin_lock_bh (& head -> lock );
656- if (sk_head (& tb -> owners ) == sk && !sk -> sk_bind_node .next ) {
657- inet_ehash_nolisten (sk , NULL );
658- spin_unlock_bh (& head -> lock );
659- return 0 ;
660- } else {
661- spin_unlock (& head -> lock );
662- /* No definite answer... Walk to established hash table */
663- ret = check_established (death_row , sk , snum , NULL );
664- out :
665- local_bh_enable ();
666- return ret ;
652+ ok :
653+ hint += i + 2 ;
654+
655+ /* Head lock still held and bh's disabled */
656+ inet_bind_hash (sk , tb , port );
657+ if (sk_unhashed (sk )) {
658+ inet_sk (sk )-> inet_sport = htons (port );
659+ inet_ehash_nolisten (sk , (struct sock * )tw );
667660 }
661+ if (tw )
662+ inet_twsk_bind_unhash (tw , hinfo );
663+ spin_unlock (& head -> lock );
664+ if (tw )
665+ inet_twsk_deschedule_put (tw );
666+ local_bh_enable ();
667+ return 0 ;
668668}
669669
670670/*
0 commit comments