--- linux-2.6.5/net/ipv4/tcp_ipv4.c.xx 2004-07-04 13:39:51.000000000 +0200 +++ linux-2.6.5/net/ipv4/tcp_ipv4.c 2004-07-04 13:51:57.000000000 +0200 @@ -2255,6 +2255,12 @@ struct hlist_node *node; struct tcp_tw_bucket *tw; + /* Avoid taking the readlock cost if we know the chain is empty, + * we have a lot of buckets. + */ + if (hlist_empty(&tcp_ehash[st->bucket].chain) && + hlist_empty(&tcp_ehash[st->bucket+tcp_ehash_size].chain)) + continue; read_lock(&tcp_ehash[st->bucket].lock); sk_for_each(sk, node, &tcp_ehash[st->bucket].chain) { if (sk->sk_family != st->family) { @@ -2301,13 +2307,17 @@ } read_unlock(&tcp_ehash[st->bucket].lock); st->state = TCP_SEQ_STATE_ESTABLISHED; - if (++st->bucket < tcp_ehash_size) { - read_lock(&tcp_ehash[st->bucket].lock); - sk = sk_head(&tcp_ehash[st->bucket].chain); - } else { + + while ((++st->bucket < tcp_ehash_size) && + hlist_empty(&tcp_ehash[st->bucket].chain) && + hlist_empty(&tcp_ehash[st->bucket+tcp_ehash_size].chain)) + /*empty*/; + if (st->bucket >= tcp_ehash_size) { cur = NULL; goto out; } + read_lock(&tcp_ehash[st->bucket].lock); + sk = sk_head(&tcp_ehash[st->bucket].chain); } else sk = sk_next(sk);