aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-4.19/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch
diff options
context:
space:
mode:
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.patch132
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);
-