Change how synchronization is done on the iptables counters. Use seqcount
wrapper instead of depending on reader/writer lock.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/netfilter/x_tables.c 2009-01-30 09:15:52.648542116 -0800
+++ b/net/netfilter/x_tables.c 2009-01-30 09:17:03.669061821 -0800
@@ -577,18 +577,36 @@ int xt_compat_target_to_user(struct xt_e
EXPORT_SYMBOL_GPL(xt_compat_target_to_user);
#endif
+static DEFINE_PER_CPU(seqcount_t, xt_counter_sequence);
+
+/* Update the counters on the current CPU. preempt must be disabled. */
void xt_add_counter(struct xt_counters *c, unsigned b, unsigned p)
{
+ seqcount_t *seq = &__get_cpu_var(xt_counter_sequence);
+
+ write_seqcount_begin(seq);
c->bcnt += b;
c->pcnt += p;
+ write_seqcount_end(seq);
}
EXPORT_SYMBOL_GPL(xt_add_counter);
+/* Fetch counters on other CPU. */
void xt_sum_counter(struct xt_counters *t, int cpu,
const struct xt_counters *c)
{
- t->pcnt += c->pcnt;
- t->bcnt += c->bcnt;
+ seqcount_t *seq = &per_cpu(xt_counter_sequence, cpu);
+ unsigned start;
+ struct xt_counters v;
+
+ /* Atomic fetch of counter value */
+ do {
+ start = read_seqcount_begin(seq);
+ v = *c;
+ } while (read_seqcount_retry(seq, start));
+
+ t->pcnt += v.pcnt;
+ t->bcnt += v.bcnt;
}
EXPORT_SYMBOL_GPL(xt_sum_counter);
--
--