On Tue, 2016-12-20 at 15:07 -0500, Josef Bacik wrote:
> --- a/net/ipv4/inet_connection_sock.c
> +++ b/net/ipv4/inet_connection_sock.c
> @@ -92,7 +92,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
>  {
>       bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
>       struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
> -     int ret = 1, attempts = 5, port = snum;
> +     int ret = 1, port = snum;
>       struct inet_bind_hashbucket *head;
>       struct net *net = sock_net(sk);
>       int i, low, high, attempt_half;
> @@ -100,6 +100,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short 
> snum)
>       kuid_t uid = sock_i_uid(sk);
>       u32 remaining, offset;
>       bool reuseport_ok = !!snum;
> +     bool empty_tb = true;
>  
>       if (port) {
>               head = &hinfo->bhash[inet_bhashfn(net, port,
> @@ -111,7 +112,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short 
> snum)
>  
>               goto tb_not_found;
>       }
> -again:
>       attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0;
>  other_half_scan:
>       inet_get_local_port_range(net, &low, &high);
> @@ -148,8 +148,12 @@ other_parity_scan:
>               spin_lock_bh(&head->lock);
>               inet_bind_bucket_for_each(tb, &head->chain)
>                       if (net_eq(ib_net(tb), net) && tb->port == port) {
> -                             if (!inet_csk_bind_conflict(sk, tb, false, 
> reuseport_ok))
> -                                     goto tb_found;
> +                             if (hlist_empty(&tb->owners))
> +                                     goto success;
> +                             if (!inet_csk_bind_conflict(sk, tb, false, 
> reuseport_ok)) {
> +                                     empty_tb = false;
> +                                     goto success;
> +                             }
>                               goto next_port;
>                       }
>               goto tb_not_found;
> @@ -184,23 +188,12 @@ tb_found:
>                     !rcu_access_pointer(sk->sk_reuseport_cb) &&
>                     sk->sk_reuseport && uid_eq(tb->fastuid, uid)))
>                       goto success;
> -             if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok)) {
> -                     if ((reuse ||
> -                          (tb->fastreuseport > 0 &&
> -                           sk->sk_reuseport &&
> -                           !rcu_access_pointer(sk->sk_reuseport_cb) &&
> -                           uid_eq(tb->fastuid, uid))) && !snum &&
> -                         --attempts >= 0) {
> -                             spin_unlock_bh(&head->lock);
> -                             goto again;
> -                     }
> +             if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok))
>                       goto fail_unlock;
> -             }
> -             if (!reuse)
> -                     tb->fastreuse = 0;
> -             if (!sk->sk_reuseport || !uid_eq(tb->fastuid, uid))
> -                     tb->fastreuseport = 0;
> -     } else {
> +             empty_tb = false;
> +     }
> +success:
> +     if (empty_tb) {


I would fine it even more simple to read, if you redo the hlist_empty
check here instead of someone has to review all the paths where this
might get set. hlist_empty is a very quick test.


Thanks,
Hannes

Reply via email to