aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inet_diag.c
diff options
context:
space:
mode:
authorEric Dumazet <dada1@cosmosbay.com>2007-11-07 05:40:20 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-11-07 07:15:11 -0500
commit230140cffa7feae90ad50bf259db1fa07674f3a7 (patch)
tree815472add31606423a508a17806b7884f0ab3e2e /net/ipv4/inet_diag.c
parentefac52762b1e3fe3035d29e82d8ee1aebc45e4a7 (diff)
[INET]: Remove per bucket rwlock in tcp/dccp ehash table.
As done two years ago on IP route cache table (commit 22c047ccbc68fa8f3fa57f0e8f906479a062c426) , 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>
Diffstat (limited to 'net/ipv4/inet_diag.c')
-rw-r--r--net/ipv4/inet_diag.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index dc429b6b0ba6..b0170732b5e9 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -747,13 +747,14 @@ skip_listen_ht:
747 747
748 for (i = s_i; i < hashinfo->ehash_size; i++) { 748 for (i = s_i; i < hashinfo->ehash_size; i++) {
749 struct inet_ehash_bucket *head = &hashinfo->ehash[i]; 749 struct inet_ehash_bucket *head = &hashinfo->ehash[i];
750 rwlock_t *lock = inet_ehash_lockp(hashinfo, i);
750 struct sock *sk; 751 struct sock *sk;
751 struct hlist_node *node; 752 struct hlist_node *node;
752 753
753 if (i > s_i) 754 if (i > s_i)
754 s_num = 0; 755 s_num = 0;
755 756
756 read_lock_bh(&head->lock); 757 read_lock_bh(lock);
757 num = 0; 758 num = 0;
758 sk_for_each(sk, node, &head->chain) { 759 sk_for_each(sk, node, &head->chain) {
759 struct inet_sock *inet = inet_sk(sk); 760 struct inet_sock *inet = inet_sk(sk);
@@ -769,7 +770,7 @@ skip_listen_ht:
769 r->id.idiag_dport) 770 r->id.idiag_dport)
770 goto next_normal; 771 goto next_normal;
771 if (inet_csk_diag_dump(sk, skb, cb) < 0) { 772 if (inet_csk_diag_dump(sk, skb, cb) < 0) {
772 read_unlock_bh(&head->lock); 773 read_unlock_bh(lock);
773 goto done; 774 goto done;
774 } 775 }
775next_normal: 776next_normal:
@@ -791,14 +792,14 @@ next_normal:
791 r->id.idiag_dport) 792 r->id.idiag_dport)
792 goto next_dying; 793 goto next_dying;
793 if (inet_twsk_diag_dump(tw, skb, cb) < 0) { 794 if (inet_twsk_diag_dump(tw, skb, cb) < 0) {
794 read_unlock_bh(&head->lock); 795 read_unlock_bh(lock);
795 goto done; 796 goto done;
796 } 797 }
797next_dying: 798next_dying:
798 ++num; 799 ++num;
799 } 800 }
800 } 801 }
801 read_unlock_bh(&head->lock); 802 read_unlock_bh(lock);
802 } 803 }
803 804
804done: 805done: