Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3ad2c17 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: core: batch nf_unregister_net_hooks synchronize_net calls



re-add batching in nf_unregister_net_hooks().

Similar as before, just store an array with to-be-free'd rule arrays
on stack, then call synchronize_net once per batch.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 2420b79f
Loading
Loading
Loading
Loading
+56 −3
Original line number Diff line number Diff line
@@ -395,10 +395,63 @@ EXPORT_SYMBOL(nf_register_net_hooks);
void nf_unregister_net_hooks(struct net *net, const struct nf_hook_ops *reg,
			     unsigned int hookcount)
{
	unsigned int i;
	struct nf_hook_entries *to_free[16], *p;
	struct nf_hook_entries __rcu **pp;
	unsigned int i, j, n;

	mutex_lock(&nf_hook_mutex);
	for (i = 0; i < hookcount; i++) {
		pp = nf_hook_entry_head(net, &reg[i]);
		if (!pp)
			continue;

		p = nf_entry_dereference(*pp);
		if (WARN_ON_ONCE(!p))
			continue;
		__nf_unregister_net_hook(p, &reg[i]);
	}
	mutex_unlock(&nf_hook_mutex);

	do {
		n = min_t(unsigned int, hookcount, ARRAY_SIZE(to_free));

		mutex_lock(&nf_hook_mutex);

		for (i = 0, j = 0; i < hookcount && j < n; i++) {
			pp = nf_hook_entry_head(net, &reg[i]);
			if (!pp)
				continue;

			p = nf_entry_dereference(*pp);
			if (!p)
				continue;

			to_free[j] = __nf_hook_entries_try_shrink(pp);
			if (to_free[j])
				++j;
		}

		mutex_unlock(&nf_hook_mutex);

		if (j) {
			unsigned int nfq;

			synchronize_net();

			/* need 2nd synchronize_net() if nfqueue is used, skb
			 * can get reinjected right before nf_queue_hook_drop()
			 */
			nfq = nf_queue_nf_hook_drop(net);
			if (nfq)
				synchronize_net();

			for (i = 0; i < j; i++)
				kvfree(to_free[i]);
		}

	for (i = 0; i < hookcount; i++)
		nf_unregister_net_hook(net, &reg[i]);
		reg += n;
		hookcount -= n;
	} while (hookcount > 0);
}
EXPORT_SYMBOL(nf_unregister_net_hooks);