* @dtype: data type (verdict or numeric type defined by userspace)
* @size: maximum set size
* @nelems: number of elements
+ * @ndeact: number of deactivated elements queued for removal
* @timeout: default timeout value in msecs
* @gc_int: garbage collection interval in msecs
* @policy: set parameterization (see enum nft_set_policies)
u32 ktype;
u32 dtype;
u32 size;
- u32 nelems;
+ atomic_t nelems;
+ u32 ndeact;
u64 timeout;
u32 gc_int;
u16 policy;
u32 flags;
int err;
- if (set->size && set->nelems == set->size)
- return -ENFILE;
-
err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
nft_set_elem_policy);
if (err < 0)
return -EBUSY;
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
+ if (set->size &&
+ !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact))
+ return -ENFILE;
+
err = nft_add_set_elem(&ctx, set, attr);
- if (err < 0)
+ if (err < 0) {
+ atomic_dec(&set->nelems);
break;
-
- set->nelems++;
+ }
}
return err;
}
if (err < 0)
break;
- set->nelems--;
+ set->ndeact++;
}
return err;
}
&te->elem,
NFT_MSG_DELSETELEM, 0);
te->set->ops->remove(te->set, &te->elem);
+ atomic_dec(&te->set->nelems);
+ te->set->ndeact--;
break;
}
}
nft_trans_destroy(trans);
break;
case NFT_MSG_NEWSETELEM:
- nft_trans_elem_set(trans)->nelems--;
te = (struct nft_trans_elem *)trans->data;
te->set->ops->remove(te->set, &te->elem);
+ atomic_dec(&te->set->nelems);
break;
case NFT_MSG_DELSETELEM:
te = (struct nft_trans_elem *)trans->data;
- nft_trans_elem_set(trans)->nelems++;
te->set->ops->activate(te->set, &te->elem);
+ te->set->ndeact--;
nft_trans_destroy(trans);
break;
static void nft_hash_gc(struct work_struct *work)
{
- const struct nft_set *set;
+ struct nft_set *set;
struct nft_hash_elem *he;
struct nft_hash *priv;
struct nft_set_gc_batch *gcb = NULL;
if (gcb == NULL)
goto out;
rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params);
+ atomic_dec(&set->nelems);
nft_set_gc_batch_add(gcb, he);
}
out: