]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/tcp_ipv4.c
tcp: Skip empty hash buckets faster in /proc/net/tcp
[linux-2.6-omap-h63xx.git] / net / ipv4 / tcp_ipv4.c
index 44c1e934824bfc024169250bbd5a47de532a91c3..37ca3843c40b2a60da712afc4fb943816af5761e 100644 (file)
@@ -1946,6 +1946,12 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
        return rc;
 }
 
+static inline int empty_bucket(struct tcp_iter_state *st)
+{
+       return hlist_empty(&tcp_hashinfo.ehash[st->bucket].chain) &&
+               hlist_empty(&tcp_hashinfo.ehash[st->bucket].twchain);
+}
+
 static void *established_get_first(struct seq_file *seq)
 {
        struct tcp_iter_state* st = seq->private;
@@ -1958,6 +1964,10 @@ static void *established_get_first(struct seq_file *seq)
                struct inet_timewait_sock *tw;
                rwlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket);
 
+               /* Lockless fast path for the common case of empty buckets */
+               if (empty_bucket(st))
+                       continue;
+
                read_lock_bh(lock);
                sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
                        if (sk->sk_family != st->family ||
@@ -2008,13 +2018,15 @@ get_tw:
                read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
                st->state = TCP_SEQ_STATE_ESTABLISHED;
 
-               if (++st->bucket < tcp_hashinfo.ehash_size) {
-                       read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
-                       sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
-               } else {
-                       cur = NULL;
-                       goto out;
-               }
+               /* Look for next non empty bucket */
+               while (++st->bucket < tcp_hashinfo.ehash_size &&
+                               empty_bucket(st))
+                       ;
+               if (st->bucket >= tcp_hashinfo.ehash_size)
+                       return NULL;
+
+               read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
+               sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
        } else
                sk = sk_next(sk);