diff options
Diffstat (limited to 'target/linux/generic/backport-4.19/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch')
-rw-r--r-- | target/linux/generic/backport-4.19/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch | 132 |
1 files changed, 0 insertions, 132 deletions
diff --git a/target/linux/generic/backport-4.19/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch b/target/linux/generic/backport-4.19/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch deleted file mode 100644 index 5eca73552b..0000000000 --- a/target/linux/generic/backport-4.19/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 8c873e2199700c2de7dbd5eedb9d90d5f109462b Mon Sep 17 00:00:00 2001 -From: Florian Westphal <fw@strlen.de> -Date: Fri, 1 Dec 2017 00:21:04 +0100 -Subject: [PATCH 04/11] netfilter: core: free hooks with call_rcu - -Giuseppe Scrivano says: - "SELinux, if enabled, registers for each new network namespace 6 - netfilter hooks." - -Cost for this is high. With synchronize_net() removed: - "The net benefit on an SMP machine with two cores is that creating a - new network namespace takes -40% of the original time." - -This patch replaces synchronize_net+kvfree with call_rcu(). -We store rcu_head at the tail of a structure that has no fixed layout, -i.e. we cannot use offsetof() to compute the start of the original -allocation. Thus store this information right after the rcu head. - -We could simplify this by just placing the rcu_head at the start -of struct nf_hook_entries. However, this structure is used in -packet processing hotpath, so only place what is needed for that -at the beginning of the struct. - -Reported-by: Giuseppe Scrivano <gscrivan@redhat.com> -Signed-off-by: Florian Westphal <fw@strlen.de> -Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ---- - include/linux/netfilter.h | 19 +++++++++++++++---- - net/netfilter/core.c | 34 ++++++++++++++++++++++++++++------ - 2 files changed, 43 insertions(+), 10 deletions(-) - ---- a/include/linux/netfilter.h -+++ b/include/linux/netfilter.h -@@ -77,17 +77,28 @@ struct nf_hook_entry { - void *priv; - }; - -+struct nf_hook_entries_rcu_head { -+ struct rcu_head head; -+ void *allocation; -+}; -+ - struct nf_hook_entries { - u16 num_hook_entries; - /* padding */ - struct nf_hook_entry hooks[]; - -- /* trailer: pointers to original orig_ops of each hook. -- * -- * This is not part of struct nf_hook_entry since its only -- * needed in slow path (hook register/unregister). -+ /* trailer: pointers to original orig_ops of each hook, -+ * followed by rcu_head and scratch space used for freeing -+ * the structure via call_rcu. - * -+ * This is not part of struct nf_hook_entry since its only -+ * needed in slow path (hook register/unregister): - * const struct nf_hook_ops *orig_ops[] -+ * -+ * For the same reason, we store this at end -- its -+ * only needed when a hook is deleted, not during -+ * packet path processing: -+ * struct nf_hook_entries_rcu_head head - */ - }; - ---- a/net/netfilter/core.c -+++ b/net/netfilter/core.c -@@ -74,7 +74,8 @@ static struct nf_hook_entries *allocate_ - struct nf_hook_entries *e; - size_t alloc = sizeof(*e) + - sizeof(struct nf_hook_entry) * num + -- sizeof(struct nf_hook_ops *) * num; -+ sizeof(struct nf_hook_ops *) * num + -+ sizeof(struct nf_hook_entries_rcu_head); - - if (num == 0) - return NULL; -@@ -85,6 +86,30 @@ static struct nf_hook_entries *allocate_ - return e; - } - -+static void __nf_hook_entries_free(struct rcu_head *h) -+{ -+ struct nf_hook_entries_rcu_head *head; -+ -+ head = container_of(h, struct nf_hook_entries_rcu_head, head); -+ kvfree(head->allocation); -+} -+ -+static void nf_hook_entries_free(struct nf_hook_entries *e) -+{ -+ struct nf_hook_entries_rcu_head *head; -+ struct nf_hook_ops **ops; -+ unsigned int num; -+ -+ if (!e) -+ return; -+ -+ num = e->num_hook_entries; -+ ops = nf_hook_entries_get_hook_ops(e); -+ head = (void *)&ops[num]; -+ head->allocation = e; -+ call_rcu(&head->head, __nf_hook_entries_free); -+} -+ - static unsigned int accept_all(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state) -@@ -291,9 +316,8 @@ int nf_register_net_hook(struct net *net - #ifdef HAVE_JUMP_LABEL - static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]); - #endif -- synchronize_net(); - BUG_ON(p == new_hooks); -- kvfree(p); -+ nf_hook_entries_free(p); - return 0; - } - EXPORT_SYMBOL(nf_register_net_hook); -@@ -361,10 +385,8 @@ void nf_unregister_net_hook(struct net * - if (!p) - return; - -- synchronize_net(); -- - nf_queue_nf_hook_drop(net); -- kvfree(p); -+ nf_hook_entries_free(p); - } - EXPORT_SYMBOL(nf_unregister_net_hook); - |