@@ -202,7 +202,9 @@ count_tree(struct net *net, struct rb_root *root,
struct xt_connlimit_conn *conn;
unsigned int count = 0;
unsigned int gc_count = 0;
+ bool no_gc = false;
+ restart:
rbnode = &(root->rb_node);
while (*rbnode) {
int diff;
@@ -230,7 +232,7 @@ count_tree(struct net *net, struct rb_root *root,
return count + 1;
}
- if (gc_count >= ARRAY_SIZE(gc_nodes))
+ if (no_gc || gc_count >= ARRAY_SIZE(gc_nodes))
continue;
/* only used for GC on hhead, retval and 'addit' ignored */
@@ -239,15 +241,22 @@ count_tree(struct net *net, struct rb_root *root,
gc_nodes[gc_count++] = rbconn;
}
+ if (gc_count) {
+ no_gc = true;
+ tree_nodes_free(root, gc_nodes, gc_count);
+ gc_count = 0;
+ goto restart;
+ }
+
/* no match, need to insert new node */
rbconn = kmem_cache_alloc(connlimit_rb_cachep, GFP_ATOMIC);
if (rbconn == NULL)
- goto out;
+ return 0;
conn = kmem_cache_alloc(connlimit_conn_cachep, GFP_ATOMIC);
if (conn == NULL) {
kmem_cache_free(connlimit_rb_cachep, rbconn);
- goto out;
+ return 0;
}
conn->tuple = *tuple;
@@ -259,10 +268,7 @@ count_tree(struct net *net, struct rb_root *root,
rb_link_node(&rbconn->node, parent, rbnode);
rb_insert_color(&rbconn->node, root);
- count = 1;
- out:
- tree_nodes_free(root, gc_nodes, gc_count);
- return count;
+ return 1;
}
static int count_them(struct net *net,