#include <asm/byteorder.h>
/* 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
*
* 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;
}
/* 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;
}
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--;
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;
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;
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)) {
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);
&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 =
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);
}
}
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;
}
}
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;
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 &&
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);