From: Florian Westphal <[email protected]>

We use an extra function with early exit for garbage collection.
It is not necessary to traverse the full list for every node since
it is enough to zap a couple of entries for garbage collection.

Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: Yi-Hung Wei <[email protected]>
---
 net/netfilter/nf_conncount.c | 40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index d8383609fe28..ed87ad40541b 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -147,6 +147,43 @@ unsigned int nf_conncount_lookup(struct net *net, struct 
hlist_head *head,
 }
 EXPORT_SYMBOL_GPL(nf_conncount_lookup);
 
+static void nf_conncount_gc_list(struct net *net,
+                                struct nf_conncount_rb *rbconn)
+{
+       const struct nf_conntrack_tuple_hash *found;
+       struct nf_conncount_tuple *conn;
+       struct hlist_node *n;
+       struct nf_conn *found_ct;
+       unsigned int collected = 0;
+
+       hlist_for_each_entry_safe(conn, n, &rbconn->hhead, node) {
+               found = nf_conntrack_find_get(net, &conn->zone, &conn->tuple);
+               if (found == NULL) {
+                       hlist_del(&conn->node);
+                       kmem_cache_free(conncount_conn_cachep, conn);
+                       collected++;
+                       continue;
+               }
+
+               found_ct = nf_ct_tuplehash_to_ctrack(found);
+               if (already_closed(found_ct)) {
+                       /*
+                        * we do not care about connections which are
+                        * closed already -> ditch it
+                        */
+                       nf_ct_put(found_ct);
+                       hlist_del(&conn->node);
+                       kmem_cache_free(conncount_conn_cachep, conn);
+                       collected++;
+                       continue;
+               }
+
+               nf_ct_put(found_ct);
+               if (collected > CONNCOUNT_GC_MAX_NODES)
+                       return;
+       }
+}
+
 static void tree_nodes_free(struct rb_root *root,
                            struct nf_conncount_rb *gc_nodes[],
                            unsigned int gc_count)
@@ -209,8 +246,7 @@ count_tree(struct net *net, struct rb_root *root,
                if (no_gc || gc_count >= ARRAY_SIZE(gc_nodes))
                        continue;
 
-               /* only used for GC on hhead, retval and 'addit' ignored */
-               nf_conncount_lookup(net, &rbconn->hhead, tuple, zone, &addit);
+               nf_conncount_gc_list(net, rbconn);
                if (hlist_empty(&rbconn->hhead))
                        gc_nodes[gc_count++] = rbconn;
        }
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to