[INET]: Remove per bucket rwlock in tcp/dccp ehash table.
As done two years ago on IP route cache table (commit
22c047ccbc
) , we can avoid using one
lock per hash bucket for the huge TCP/DCCP hash tables.
On a typical x86_64 platform, this saves about 2MB or 4MB of ram, for
litle performance differences. (we hit a different cache line for the
rwlock, but then the bucket cache line have a better sharing factor
among cpus, since we dirty it less often). For netstat or ss commands
that want a full scan of hash table, we perform fewer memory accesses.
Using a 'small' table of hashed rwlocks should be more than enough to
provide correct SMP concurrency between different buckets, without
using too much memory. Sizing of this table depends on
num_possible_cpus() and various CONFIG settings.
This patch provides some locking abstraction that may ease a future
work using a different model for TCP/DCCP table.
Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
efac52762b
commit
230140cffa
@@ -20,16 +20,16 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw,
|
||||
struct inet_bind_hashbucket *bhead;
|
||||
struct inet_bind_bucket *tb;
|
||||
/* Unlink from established hashes. */
|
||||
struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, tw->tw_hash);
|
||||
rwlock_t *lock = inet_ehash_lockp(hashinfo, tw->tw_hash);
|
||||
|
||||
write_lock(&ehead->lock);
|
||||
write_lock(lock);
|
||||
if (hlist_unhashed(&tw->tw_node)) {
|
||||
write_unlock(&ehead->lock);
|
||||
write_unlock(lock);
|
||||
return;
|
||||
}
|
||||
__hlist_del(&tw->tw_node);
|
||||
sk_node_init(&tw->tw_node);
|
||||
write_unlock(&ehead->lock);
|
||||
write_unlock(lock);
|
||||
|
||||
/* Disassociate with bind bucket. */
|
||||
bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)];
|
||||
@@ -59,6 +59,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
|
||||
const struct inet_sock *inet = inet_sk(sk);
|
||||
const struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, sk->sk_hash);
|
||||
rwlock_t *lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
|
||||
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
|
||||
@@ -71,7 +72,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
|
||||
inet_twsk_add_bind_node(tw, &tw->tw_tb->owners);
|
||||
spin_unlock(&bhead->lock);
|
||||
|
||||
write_lock(&ehead->lock);
|
||||
write_lock(lock);
|
||||
|
||||
/* Step 2: Remove SK from established hash. */
|
||||
if (__sk_del_node_init(sk))
|
||||
@@ -81,7 +82,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
|
||||
inet_twsk_add_node(tw, &ehead->twchain);
|
||||
atomic_inc(&tw->tw_refcnt);
|
||||
|
||||
write_unlock(&ehead->lock);
|
||||
write_unlock(lock);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(__inet_twsk_hashdance);
|
||||
|
Reference in New Issue
Block a user