summaryrefslogtreecommitdiffstats
path: root/net/ipv6/inet6_hashtables.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2008-01-31 14:04:45 +0100
committerDavid S. Miller <davem@davemloft.net>2008-02-01 04:28:17 +0100
commit5ee31fc1ecdcbc234c8c56dcacef87c8e09909d8 (patch)
tree5fe73acbcf784f9ee326d7d10ae217c7b4eb13ee /net/ipv6/inet6_hashtables.c
parent[IPV6]: Introduce the INET6_TW_MATCH macro. (diff)
downloadlinux-5ee31fc1ecdcbc234c8c56dcacef87c8e09909d8.tar.xz
linux-5ee31fc1ecdcbc234c8c56dcacef87c8e09909d8.zip
[INET]: Consolidate inet(6)_hash_connect.
These two functions are the same except for what they call to "check_established" and "hash" for a socket. This saves half-a-kilo for ipv4 and ipv6. add/remove: 1/0 grow/shrink: 1/4 up/down: 582/-1128 (-546) function old new delta __inet_hash_connect - 577 +577 arp_ignore 108 113 +5 static.hint 8 4 -4 rt_worker_func 376 372 -4 inet6_hash_connect 584 25 -559 inet_hash_connect 586 25 -561 Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/inet6_hashtables.c')
-rw-r--r--net/ipv6/inet6_hashtables.c93
1 files changed, 2 insertions, 91 deletions
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 06b01befc90e..ece6d0ee2da5 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -233,97 +233,8 @@ static inline u32 inet6_sk_port_offset(const struct sock *sk)
int inet6_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk)
{
- struct inet_hashinfo *hinfo = death_row->hashinfo;
- const unsigned short snum = inet_sk(sk)->num;
- struct inet_bind_hashbucket *head;
- struct inet_bind_bucket *tb;
- int ret;
-
- if (snum == 0) {
- int i, port, low, high, remaining;
- static u32 hint;
- const u32 offset = hint + inet6_sk_port_offset(sk);
- struct hlist_node *node;
- struct inet_timewait_sock *tw = NULL;
-
- inet_get_local_port_range(&low, &high);
- remaining = (high - low) + 1;
-
- local_bh_disable();
- for (i = 1; i <= remaining; i++) {
- port = low + (i + offset) % remaining;
- head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
- spin_lock(&head->lock);
-
- /* Does not bother with rcv_saddr checks,
- * because the established check is already
- * unique enough.
- */
- inet_bind_bucket_for_each(tb, node, &head->chain) {
- if (tb->port == port) {
- BUG_TRAP(!hlist_empty(&tb->owners));
- if (tb->fastreuse >= 0)
- goto next_port;
- if (!__inet6_check_established(death_row,
- sk, port,
- &tw))
- goto ok;
- goto next_port;
- }
- }
-
- tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
- head, port);
- if (!tb) {
- spin_unlock(&head->lock);
- break;
- }
- tb->fastreuse = -1;
- goto ok;
-
- next_port:
- spin_unlock(&head->lock);
- }
- local_bh_enable();
-
- return -EADDRNOTAVAIL;
-
-ok:
- hint += i;
-
- /* Head lock still held and bh's disabled */
- inet_bind_hash(sk, tb, port);
- if (sk_unhashed(sk)) {
- inet_sk(sk)->sport = htons(port);
- __inet6_hash(hinfo, sk);
- }
- spin_unlock(&head->lock);
-
- if (tw) {
- inet_twsk_deschedule(tw, death_row);
- inet_twsk_put(tw);
- }
-
- ret = 0;
- goto out;
- }
-
- head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
- tb = inet_csk(sk)->icsk_bind_hash;
- spin_lock_bh(&head->lock);
-
- if (sk_head(&tb->owners) == sk && sk->sk_bind_node.next == NULL) {
- __inet6_hash(hinfo, sk);
- spin_unlock_bh(&head->lock);
- return 0;
- } else {
- spin_unlock(&head->lock);
- /* No definite answer... Walk to established hash table */
- ret = __inet6_check_established(death_row, sk, snum, NULL);
-out:
- local_bh_enable();
- return ret;
- }
+ return __inet_hash_connect(death_row, sk,
+ __inet6_check_established, __inet6_hash);
}
EXPORT_SYMBOL_GPL(inet6_hash_connect);