aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <dada1@cosmosbay.com>2008-01-18 07:30:21 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-20 23:31:39 -0500
commit8d3f099abe25c21670cb5728178a1f286952782d (patch)
tree074339fd500a3af4f89cab67c0a90bae81bc93a7 /net
parent49d85c502ec5e6d5998c1a04394c5b24e8f7d32d (diff)
[IPV4] FIB_HASH : Avoid unecessary loop in fn_hash_dump_zone()
I noticed "ip route list" was slower than "cat /proc/net/route" on a machine with a full Internet routing table (214392 entries : Special thanks to Robert ;) ) This is similar to problem reported in commit d8c9283089287341c85a0a69de32c2287a990e71 ("[IPV4] ROUTE: ip_rt_dump() is unecessary slow") Fix is to avoid scanning the begining of fz_hash table, but directly seek to the right offset. Before patch : time ip route >/tmp/ROUTE real 0m1.285s user 0m0.712s sys 0m0.436s After patch # time ip route >/tmp/ROUTE real 0m0.835s user 0m0.692s sys 0m0.124s Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/fib_hash.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 99071d79c5e7..0dfee27cfbcd 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -721,19 +721,18 @@ fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb,
721{ 721{
722 int h, s_h; 722 int h, s_h;
723 723
724 if (fz->fz_hash == NULL)
725 return skb->len;
724 s_h = cb->args[3]; 726 s_h = cb->args[3];
725 for (h=0; h < fz->fz_divisor; h++) { 727 for (h = s_h; h < fz->fz_divisor; h++) {
726 if (h < s_h) continue; 728 if (hlist_empty(&fz->fz_hash[h]))
727 if (h > s_h)
728 memset(&cb->args[4], 0,
729 sizeof(cb->args) - 4*sizeof(cb->args[0]));
730 if (fz->fz_hash == NULL ||
731 hlist_empty(&fz->fz_hash[h]))
732 continue; 729 continue;
733 if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h])<0) { 730 if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h]) < 0) {
734 cb->args[3] = h; 731 cb->args[3] = h;
735 return -1; 732 return -1;
736 } 733 }
734 memset(&cb->args[4], 0,
735 sizeof(cb->args) - 4*sizeof(cb->args[0]));
737 } 736 }
738 cb->args[3] = h; 737 cb->args[3] = h;
739 return skb->len; 738 return skb->len;
@@ -749,14 +748,13 @@ static int fn_hash_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin
749 read_lock(&fib_hash_lock); 748 read_lock(&fib_hash_lock);
750 for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) { 749 for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
751 if (m < s_m) continue; 750 if (m < s_m) continue;
752 if (m > s_m)
753 memset(&cb->args[3], 0,
754 sizeof(cb->args) - 3*sizeof(cb->args[0]));
755 if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) { 751 if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
756 cb->args[2] = m; 752 cb->args[2] = m;
757 read_unlock(&fib_hash_lock); 753 read_unlock(&fib_hash_lock);
758 return -1; 754 return -1;
759 } 755 }
756 memset(&cb->args[3], 0,
757 sizeof(cb->args) - 3*sizeof(cb->args[0]));
760 } 758 }
761 read_unlock(&fib_hash_lock); 759 read_unlock(&fib_hash_lock);
762 cb->args[2] = m; 760 cb->args[2] = m;