[SNMP]: Fix SNMP counters with PREEMPT
authorHerbert Xu <herbert@gondor.apana.org.au>
Thu, 20 Dec 2007 12:13:21 +0000 (04:13 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 22:59:16 +0000 (14:59 -0800)
The SNMP macros use raw_smp_processor_id() in process context
which is illegal because the process may be preempted and then
migrated to another CPU.

This patch makes it use get_cpu/put_cpu to disable preemption.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/snmp.h

index 9c5793db637fcb70dda9f8bebc73fbe27e2ceafb..fbb66663a42cb3fa1eb1cbc68bad11c98703f03e 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/cache.h>
 #include <linux/snmp.h>
+#include <linux/smp.h>
 
 /*
  * Mibs are stored in array of unsigned long.
@@ -135,14 +136,26 @@ struct linux_mib {
 #define SNMP_INC_STATS_BH(mib, field)  \
        (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field]++)
 #define SNMP_INC_STATS_USER(mib, field) \
-       (per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field]++)
+       do { \
+               per_cpu_ptr(mib[1], get_cpu())->mibs[field]++; \
+               put_cpu(); \
+       } while (0)
 #define SNMP_INC_STATS(mib, field)     \
-       (per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]++)
+       do { \
+               per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]++; \
+               put_cpu(); \
+       } while (0)
 #define SNMP_DEC_STATS(mib, field)     \
-       (per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]--)
+       do { \
+               per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
+               put_cpu(); \
+       } while (0)
 #define SNMP_ADD_STATS_BH(mib, field, addend)  \
        (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend)        \
-       (per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field] += addend)
+       do { \
+               per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \
+               put_cpu(); \
+       } while (0)
 
 #endif