summaryrefslogtreecommitdiffstats
path: root/net/netfilter/nf_tables_api.c
diff options
context:
space:
mode:
authorPatrick McHardy2015-03-25 15:08:47 +0100
committerPablo Neira Ayuso2015-03-26 11:09:34 +0100
commit61edafbb47e9f46fb850035b1f8f062564445704 (patch)
tree9adc749e66e69c6cd5b1d82434ab00bf1c406670 /net/netfilter/nf_tables_api.c
parentnetfilter: nf_tables: convert hash and rbtree to set extensions (diff)
downloadkernel-qcow2-linux-61edafbb47e9f46fb850035b1f8f062564445704.tar.gz
kernel-qcow2-linux-61edafbb47e9f46fb850035b1f8f062564445704.tar.xz
kernel-qcow2-linux-61edafbb47e9f46fb850035b1f8f062564445704.zip
netfilter: nf_tables: consolide set element destruction
With the conversion to set extensions, it is now possible to consolidate the different set element destruction functions. The set implementations' ->remove() functions are changed to only take the element out of their internal data structures. Elements will be freed in a batched fashion after the global transaction's completion RCU grace period. This reduces the amount of grace periods required for nft_hash from N to zero additional ones, additionally this guarantees that the set elements' extensions of all implementations can be used under RCU protection. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nf_tables_api.c')
-rw-r--r--net/netfilter/nf_tables_api.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 99cb884b985f..b35512f1934c 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3155,6 +3155,18 @@ static void *nft_set_elem_init(const struct nft_set *set,
return elem;
}
+void nft_set_elem_destroy(const struct nft_set *set, void *elem)
+{
+ struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
+
+ nft_data_uninit(nft_set_ext_key(ext), NFT_DATA_VALUE);
+ if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
+ nft_data_uninit(nft_set_ext_data(ext), set->dtype);
+
+ kfree(elem);
+}
+EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
+
static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
const struct nlattr *attr)
{
@@ -3596,6 +3608,10 @@ static void nf_tables_commit_release(struct nft_trans *trans)
case NFT_MSG_DELSET:
nft_set_destroy(nft_trans_set(trans));
break;
+ case NFT_MSG_DELSETELEM:
+ nft_set_elem_destroy(nft_trans_elem_set(trans),
+ nft_trans_elem(trans).priv);
+ break;
}
kfree(trans);
}
@@ -3605,7 +3621,6 @@ static int nf_tables_commit(struct sk_buff *skb)
struct net *net = sock_net(skb->sk);
struct nft_trans *trans, *next;
struct nft_trans_elem *te;
- struct nft_set_ext *ext;
/* Bump generation counter, invalidate any dump in progress */
while (++net->nft.base_seq == 0);
@@ -3690,18 +3705,12 @@ static int nf_tables_commit(struct sk_buff *skb)
break;
case NFT_MSG_DELSETELEM:
te = (struct nft_trans_elem *)trans->data;
- ext = nft_set_elem_ext(te->set, te->elem.priv);
nf_tables_setelem_notify(&trans->ctx, te->set,
&te->elem,
NFT_MSG_DELSETELEM, 0);
te->set->ops->get(te->set, &te->elem);
- nft_data_uninit(&te->elem.key, NFT_DATA_VALUE);
- if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
- nft_data_uninit(nft_set_ext_data(ext),
- te->set->dtype);
te->set->ops->remove(te->set, &te->elem);
- nft_trans_destroy(trans);
break;
}
}
@@ -3733,6 +3742,10 @@ static void nf_tables_abort_release(struct nft_trans *trans)
case NFT_MSG_NEWSET:
nft_set_destroy(nft_trans_set(trans));
break;
+ case NFT_MSG_NEWSETELEM:
+ nft_set_elem_destroy(nft_trans_elem_set(trans),
+ nft_trans_elem(trans).priv);
+ break;
}
kfree(trans);
}
@@ -3742,7 +3755,6 @@ static int nf_tables_abort(struct sk_buff *skb)
struct net *net = sock_net(skb->sk);
struct nft_trans *trans, *next;
struct nft_trans_elem *te;
- struct nft_set_ext *ext;
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
switch (trans->msg_type) {
@@ -3804,15 +3816,9 @@ static int nf_tables_abort(struct sk_buff *skb)
case NFT_MSG_NEWSETELEM:
nft_trans_elem_set(trans)->nelems--;
te = (struct nft_trans_elem *)trans->data;
- ext = nft_set_elem_ext(te->set, te->elem.priv);
te->set->ops->get(te->set, &te->elem);
- nft_data_uninit(&te->elem.key, NFT_DATA_VALUE);
- if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
- nft_data_uninit(nft_set_ext_data(ext),
- te->set->dtype);
te->set->ops->remove(te->set, &te->elem);
- nft_trans_destroy(trans);
break;
case NFT_MSG_DELSETELEM:
nft_trans_elem_set(trans)->nelems++;