Re: [PATCH nf 3/3] netfilter: nf_conncount: speculative garbage collection on empty lists

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> wrote:
> Instead of removing a empty list node that might be reintroduced soon
> thereafter, tentatively place the empty list node in the garbage
> collector, then re-check if the list is empty again before deleting it.

The gc is removed in your first patch.

> -	NF_CONNCOUNT_SKIP,	/* list is already reclaimed by gc */

I would keep this, and rename it to
NF_CONNCOUNT_LOCK,	/* fall back to full locking */

>  };
>  
>  struct nf_conncount_list {
>  	spinlock_t list_lock;
>  	struct list_head head;	/* connections with the same filtering key */
>  	unsigned int count;	/* length of list */
> -	bool dead;
>  };

Ack, dead should be removed.

>  struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
> diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
> index 68788b979c1d..b33df77bd7a3 100644
> --- a/net/netfilter/nf_conncount.c
> +++ b/net/netfilter/nf_conncount.c
> @@ -103,11 +103,6 @@ nf_conncount_add(struct nf_conncount_list *list,
>  	conn->cpu = raw_smp_processor_id();
>  	conn->jiffies32 = (u32)jiffies;
>  	spin_lock_bh(&list->list_lock);
> -	if (list->dead == true) {
> -		kmem_cache_free(conncount_conn_cachep, conn);
> -		spin_unlock_bh(&list->list_lock);
> -		return NF_CONNCOUNT_SKIP;

Make this return NF_CONNCOUNT_LOCK.

> @@ -310,13 +285,18 @@ static void tree_nodes_free(struct rb_root *root,
>  			    unsigned int gc_count)
>  {
>  	struct nf_conncount_rb *rbconn;
> +	bool release = false;
>  
>  	while (gc_count) {
>  		rbconn = gc_nodes[--gc_count];
>  		spin_lock(&rbconn->list.list_lock);
> +		if (!rbconn->list.count) {
> +			release = true;
> +			rb_erase(&rbconn->node, root);
> +		}
>  		spin_unlock(&rbconn->list.list_lock);
> +		if (release)
> +			call_rcu(&rbconn->rcu_head, __tree_nodes_free);

This looks good.

> @@ -360,11 +340,6 @@ insert_tree(struct net *net,
>  				count = 0; /* hotdrop */
>  			} else if (ret == NF_CONNCOUNT_ADDED) {
>  				count = rbconn->list.count;
> -			} else {
> -				/* NF_CONNCOUNT_SKIP, rbconn is already
> -				 * reclaimed by gc, insert a new tree node
> -				 */
> -				node_found = false;

I would alter the comment:

/* NF_CONNCOUNT_LOCK, rbconn might be on a gc list already,
 * fall back to locked version.
 */

insert_tree() has a good chance of re-using the as is.
I also think its not worth to optimize that case in any way.

In normal operation tree node insert/removal should be rare
compared to changes to lists/rb_nodes.



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux