aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/nf_tables_core.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2014-07-09 15:14:06 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2014-07-14 12:00:17 +0200
commitce355e209feb030945dae4c358c02f29a84f3f8b (patch)
treeedf8561e59627f889581be27fc80c86820c2988e /net/netfilter/nf_tables_core.c
parentnetfilter: nf_tables: set NLM_F_DUMP_INTR if netlink dumping is stale (diff)
downloadlinux-dev-ce355e209feb030945dae4c358c02f29a84f3f8b.tar.xz
linux-dev-ce355e209feb030945dae4c358c02f29a84f3f8b.zip
netfilter: nf_tables: 64bit stats need some extra synchronization
Use generic u64_stats_sync infrastructure to get proper 64bit stats, even on 32bit arches, at no extra cost for 64bit arches. Without this fix, 32bit arches can have some wrong counters at the time the carry is propagated into upper word. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to '')
-rw-r--r--net/netfilter/nf_tables_core.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 345acfb1720b..3b90eb2b2c55 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -109,7 +109,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
struct nft_data data[NFT_REG_MAX + 1];
unsigned int stackptr = 0;
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
- struct nft_stats __percpu *stats;
+ struct nft_stats *stats;
int rulenum;
/*
* Cache cursor to avoid problems in case that the cursor is updated
@@ -205,9 +205,11 @@ next_rule:
nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY);
rcu_read_lock_bh();
- stats = rcu_dereference(nft_base_chain(basechain)->stats);
- __this_cpu_inc(stats->pkts);
- __this_cpu_add(stats->bytes, pkt->skb->len);
+ stats = this_cpu_ptr(rcu_dereference(nft_base_chain(basechain)->stats));
+ u64_stats_update_begin(&stats->syncp);
+ stats->pkts++;
+ stats->bytes += pkt->skb->len;
+ u64_stats_update_end(&stats->syncp);
rcu_read_unlock_bh();
return nft_base_chain(basechain)->policy;