--- linux-2.6.20/include/net/inet_hashtables.h 2007-02-07 09:19:22.000000000 +0100 +++ linux-2.6.20-ed/include/net/inet_hashtables.h 2007-02-07 12:20:47.000000000 +0100 @@ -34,12 +34,13 @@ #include /* This is for all connections with a full identity, no wildcards. - * New scheme, half the table is for TIME_WAIT, the other half is - * for the rest. I'll experiment with dynamic table growth later. + * One chain is dedicated to TIME_WAIT sockets. + * I'll experiment with dynamic table growth later. */ struct inet_ehash_bucket { rwlock_t lock; struct hlist_head chain; + struct hlist_head twchain; }; /* There are a few simple rules, which allow for local port reuse by @@ -97,8 +98,7 @@ struct inet_hashinfo { * * TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE * - * First half of the table is for sockets not in TIME_WAIT, second half - * is for TIME_WAIT sockets only. + * TIME_WAIT sockets use a separate chain (twchain). */ struct inet_ehash_bucket *ehash; @@ -369,7 +369,7 @@ static inline struct sock * } /* Must check for a TIME_WAIT'er before going to listener hash. */ - sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { + sk_for_each(sk, node, &head->twchain) { if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif)) goto hit; } --- linux-2.6.20/net/ipv4/tcp_ipv4.c 2007-02-07 09:09:40.000000000 +0100 +++ linux-2.6.20-ed/net/ipv4/tcp_ipv4.c 2007-02-07 09:42:26.000000000 +0100 @@ -2051,7 +2051,7 @@ static void *established_get_first(struc } st->state = TCP_SEQ_STATE_TIME_WAIT; inet_twsk_for_each(tw, node, - &tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain) { + &tcp_hashinfo.ehash[st->bucket].twchain) { if (tw->tw_family != st->family) { continue; } @@ -2107,7 +2107,7 @@ get_tw: } st->state = TCP_SEQ_STATE_TIME_WAIT; - tw = tw_head(&tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain); + tw = tw_head(&tcp_hashinfo.ehash[st->bucket].twchain); goto get_tw; found: cur = sk; --- linux-2.6.20/net/ipv4/tcp.c 2007-02-07 09:09:40.000000000 +0100 +++ linux-2.6.20-ed/net/ipv4/tcp.c 2007-02-07 09:33:33.000000000 +0100 @@ -2415,10 +2415,11 @@ void __init tcp_init(void) &tcp_hashinfo.ehash_size, NULL, 0); - tcp_hashinfo.ehash_size = (1 << tcp_hashinfo.ehash_size) >> 1; - for (i = 0; i < (tcp_hashinfo.ehash_size << 1); i++) { + tcp_hashinfo.ehash_size = 1 << tcp_hashinfo.ehash_size; + for (i = 0; i < tcp_hashinfo.ehash_size; i++) { rwlock_init(&tcp_hashinfo.ehash[i].lock); INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].chain); + INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].twchain); } tcp_hashinfo.bhash = @@ -2475,7 +2476,7 @@ void __init tcp_init(void) printk(KERN_INFO "TCP: Hash tables configured " "(established %d bind %d)\n", - tcp_hashinfo.ehash_size << 1, tcp_hashinfo.bhash_size); + tcp_hashinfo.ehash_size, tcp_hashinfo.bhash_size); tcp_register_congestion_control(&tcp_reno); } --- linux-2.6.20/net/ipv4/inet_timewait_sock.c 2007-02-07 09:09:40.000000000 +0100 +++ linux-2.6.20-ed/net/ipv4/inet_timewait_sock.c 2007-02-07 09:33:33.000000000 +0100 @@ -78,8 +78,8 @@ void __inet_twsk_hashdance(struct inet_t if (__sk_del_node_init(sk)) sock_prot_dec_use(sk->sk_prot); - /* Step 3: Hash TW into TIMEWAIT half of established hash table. */ - inet_twsk_add_node(tw, &(ehead + hashinfo->ehash_size)->chain); + /* Step 3: Hash TW into TIMEWAIT chain. */ + inet_twsk_add_node(tw, &ehead->twchain); atomic_inc(&tw->tw_refcnt); write_unlock(&ehead->lock); --- linux-2.6.20/net/ipv4/inet_hashtables.c 2007-02-07 09:09:40.000000000 +0100 +++ linux-2.6.20-ed/net/ipv4/inet_hashtables.c 2007-02-07 09:33:33.000000000 +0100 @@ -212,7 +212,7 @@ static int __inet_check_established(stru write_lock(&head->lock); /* Check TIME-WAIT sockets first. */ - sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) { + sk_for_each(sk2, node, &head->twchain) { tw = inet_twsk(sk2); if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) { --- linux-2.6.20/net/ipv4/inet_diag.c 2007-02-07 09:09:40.000000000 +0100 +++ linux-2.6.20-ed/net/ipv4/inet_diag.c 2007-02-07 09:33:33.000000000 +0100 @@ -775,7 +775,7 @@ next_normal: struct inet_timewait_sock *tw; inet_twsk_for_each(tw, node, - &hashinfo->ehash[i + hashinfo->ehash_size].chain) { + &head->twchain) { if (num < s_num) goto next_dying; --- linux-2.6.20/net/dccp/proto.c 2007-02-07 10:50:36.000000000 +0100 +++ linux-2.6.20-ed/net/dccp/proto.c 2007-02-07 10:55:10.000000000 +0100 @@ -1024,7 +1024,6 @@ static int __init dccp_init(void) do { dccp_hashinfo.ehash_size = (1UL << ehash_order) * PAGE_SIZE / sizeof(struct inet_ehash_bucket); - dccp_hashinfo.ehash_size >>= 1; while (dccp_hashinfo.ehash_size & (dccp_hashinfo.ehash_size - 1)) dccp_hashinfo.ehash_size--; @@ -1037,9 +1036,10 @@ static int __init dccp_init(void) goto out_free_bind_bucket_cachep; } - for (i = 0; i < (dccp_hashinfo.ehash_size << 1); i++) { + for (i = 0; i < dccp_hashinfo.ehash_size; i++) { rwlock_init(&dccp_hashinfo.ehash[i].lock); INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain); + INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].twchain); } bhash_order = ehash_order; --- linux-2.6.20/net/ipv6/inet6_hashtables.c 2007-02-07 10:53:33.000000000 +0100 +++ linux-2.6.20-ed/net/ipv6/inet6_hashtables.c 2007-02-07 10:55:10.000000000 +0100 @@ -79,7 +79,7 @@ struct sock *__inet6_lookup_established( goto hit; /* You sunk my battleship! */ } /* Must check for a TIME_WAIT'er before going to listener hash. */ - sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { + sk_for_each(sk, node, &head->twchain) { const struct inet_timewait_sock *tw = inet_twsk(sk); if(*((__portpair *)&(tw->tw_dport)) == ports && @@ -183,7 +183,7 @@ static int __inet6_check_established(str write_lock(&head->lock); /* Check TIME-WAIT sockets first. */ - sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) { + sk_for_each(sk2, node, &head->twchain) { const struct inet6_timewait_sock *tw6 = inet6_twsk(sk2); tw = inet_twsk(sk2);