diff options
author | Florian Westphal <fw@strlen.de> | 2017-10-12 01:13:51 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2017-10-24 18:01:50 +0200 |
commit | d13e7b2e65f6dfbe97b845d75741a970181b9fec (patch) | |
tree | c0387e21f2af12e91f485ac0c944cefab9359a2a /net/ipv6 | |
parent | netfilter: x_tables: make xt_replace_table wait until old rules are not used ... (diff) | |
download | linux-d13e7b2e65f6dfbe97b845d75741a970181b9fec.tar.xz linux-d13e7b2e65f6dfbe97b845d75741a970181b9fec.zip |
netfilter: x_tables: don't use seqlock when fetching old counters
after previous commit xt_replace_table will wait until all cpus
had even seqcount (i.e., no cpu is accessing old ruleset).
Add a 'old' counter retrival version that doesn't synchronize counters.
Its not needed, the old counters are not in use anymore at this point.
This speeds up table replacement on busy systems with large tables
(and many cores).
Cc: Dan Williams <dcbw@redhat.com>
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 01bd3ee5ebc6..f06e25065a34 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -800,6 +800,25 @@ get_counters(const struct xt_table_info *t, } } +static void get_old_counters(const struct xt_table_info *t, + struct xt_counters counters[]) +{ + struct ip6t_entry *iter; + unsigned int cpu, i; + + for_each_possible_cpu(cpu) { + i = 0; + xt_entry_foreach(iter, t->entries, t->size) { + const struct xt_counters *tmp; + + tmp = xt_get_per_cpu_counter(&iter->counters, cpu); + ADD_COUNTER(counters[i], tmp->bcnt, tmp->pcnt); + ++i; + } + cond_resched(); + } +} + static struct xt_counters *alloc_counters(const struct xt_table *table) { unsigned int countersize; @@ -1090,8 +1109,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, (newinfo->number <= oldinfo->initial_entries)) module_put(t->me); - /* Get the old counters, and synchronize with replace */ - get_counters(oldinfo, counters); + get_old_counters(oldinfo, counters); /* Decrease module usage counts and free resource */ xt_entry_foreach(iter, oldinfo->entries, oldinfo->size) |