[INET]: Generalise the TCP sock ID lookup routines
And also some TIME_WAIT functions. [acme@toy net-2.6.14]$ grep built-in /tmp/before.size /tmp/after.size /tmp/before.size: 282955 13122 9312 305389 4a8ed net/ipv4/built-in.o /tmp/after.size: 281566 13122 9312 304000 4a380 net/ipv4/built-in.o [acme@toy net-2.6.14]$ I kept them still inlined, will uninline at some point to see what would be the performance difference. Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
8feaf0c0a5
commit
e48c414ee6
83
net/ipv4/inet_timewait_sock.c
Normal file
83
net/ipv4/inet_timewait_sock.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* INET An implementation of the TCP/IP protocol suite for the LINUX
|
||||
* operating system. INET is implemented using the BSD Socket
|
||||
* interface as the means of communication with the user level.
|
||||
*
|
||||
* Generic TIME_WAIT sockets functions
|
||||
*
|
||||
* From code orinally in TCP
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <net/inet_hashtables.h>
|
||||
#include <net/inet_timewait_sock.h>
|
||||
|
||||
/* Must be called with locally disabled BHs. */
|
||||
void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo)
|
||||
{
|
||||
struct inet_bind_hashbucket *bhead;
|
||||
struct inet_bind_bucket *tb;
|
||||
/* Unlink from established hashes. */
|
||||
struct inet_ehash_bucket *ehead = &hashinfo->ehash[tw->tw_hashent];
|
||||
|
||||
write_lock(&ehead->lock);
|
||||
if (hlist_unhashed(&tw->tw_node)) {
|
||||
write_unlock(&ehead->lock);
|
||||
return;
|
||||
}
|
||||
__hlist_del(&tw->tw_node);
|
||||
sk_node_init(&tw->tw_node);
|
||||
write_unlock(&ehead->lock);
|
||||
|
||||
/* Disassociate with bind bucket. */
|
||||
bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)];
|
||||
spin_lock(&bhead->lock);
|
||||
tb = tw->tw_tb;
|
||||
__hlist_del(&tw->tw_bind_node);
|
||||
tw->tw_tb = NULL;
|
||||
inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
|
||||
spin_unlock(&bhead->lock);
|
||||
#ifdef SOCK_REFCNT_DEBUG
|
||||
if (atomic_read(&tw->tw_refcnt) != 1) {
|
||||
printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n",
|
||||
tw->tw_prot->name, tw, atomic_read(&tw->tw_refcnt));
|
||||
}
|
||||
#endif
|
||||
inet_twsk_put(tw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter the time wait state. This is called with locally disabled BH.
|
||||
* Essentially we whip up a timewait bucket, copy the relevant info into it
|
||||
* from the SK, and mess with hash chains and list linkage.
|
||||
*/
|
||||
void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
|
||||
struct inet_hashinfo *hashinfo)
|
||||
{
|
||||
const struct inet_sock *inet = inet_sk(sk);
|
||||
struct inet_ehash_bucket *ehead = &hashinfo->ehash[sk->sk_hashent];
|
||||
struct inet_bind_hashbucket *bhead;
|
||||
/* Step 1: Put TW into bind hash. Original socket stays there too.
|
||||
Note, that any socket with inet->num != 0 MUST be bound in
|
||||
binding cache, even if it is closed.
|
||||
*/
|
||||
bhead = &hashinfo->bhash[inet_bhashfn(inet->num, hashinfo->bhash_size)];
|
||||
spin_lock(&bhead->lock);
|
||||
tw->tw_tb = inet->bind_hash;
|
||||
BUG_TRAP(inet->bind_hash);
|
||||
inet_twsk_add_bind_node(tw, &tw->tw_tb->owners);
|
||||
spin_unlock(&bhead->lock);
|
||||
|
||||
write_lock(&ehead->lock);
|
||||
|
||||
/* Step 2: Remove SK from established hash. */
|
||||
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);
|
||||
atomic_inc(&tw->tw_refcnt);
|
||||
|
||||
write_unlock(&ehead->lock);
|
||||
}
|
Reference in New Issue
Block a user