提交 5d235d6c 编写于 作者: P Pablo Neira Ayuso

netfilter: nft_set_rbtree: skip elements in transaction from garbage collection

Skip interference with an ongoing transaction, do not perform garbage
collection on inactive elements. Reset annotated previous end interval
if the expired element is marked as busy (control plane removed the
element right before expiration).

Fixes: 8d8540c4 ("netfilter: nft_set_rbtree: add timeout support")
Reviewed-by: NStefano Brivio <sbrivio@redhat.com>
Signed-off-by: NPablo Neira Ayuso <pablo@netfilter.org>
上级 c9e6978e
...@@ -563,23 +563,37 @@ static void nft_rbtree_gc(struct work_struct *work) ...@@ -563,23 +563,37 @@ static void nft_rbtree_gc(struct work_struct *work)
struct nft_rbtree *priv; struct nft_rbtree *priv;
struct rb_node *node; struct rb_node *node;
struct nft_set *set; struct nft_set *set;
struct net *net;
u8 genmask;
priv = container_of(work, struct nft_rbtree, gc_work.work); priv = container_of(work, struct nft_rbtree, gc_work.work);
set = nft_set_container_of(priv); set = nft_set_container_of(priv);
net = read_pnet(&set->net);
genmask = nft_genmask_cur(net);
write_lock_bh(&priv->lock); write_lock_bh(&priv->lock);
write_seqcount_begin(&priv->count); write_seqcount_begin(&priv->count);
for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
rbe = rb_entry(node, struct nft_rbtree_elem, node); rbe = rb_entry(node, struct nft_rbtree_elem, node);
if (!nft_set_elem_active(&rbe->ext, genmask))
continue;
/* elements are reversed in the rbtree for historical reasons,
* from highest to lowest value, that is why end element is
* always visited before the start element.
*/
if (nft_rbtree_interval_end(rbe)) { if (nft_rbtree_interval_end(rbe)) {
rbe_end = rbe; rbe_end = rbe;
continue; continue;
} }
if (!nft_set_elem_expired(&rbe->ext)) if (!nft_set_elem_expired(&rbe->ext))
continue; continue;
if (nft_set_elem_mark_busy(&rbe->ext))
if (nft_set_elem_mark_busy(&rbe->ext)) {
rbe_end = NULL;
continue; continue;
}
if (rbe_prev) { if (rbe_prev) {
rb_erase(&rbe_prev->node, &priv->root); rb_erase(&rbe_prev->node, &priv->root);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册