diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-06-01 06:00:41 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-06-01 06:00:41 -0400 |
commit | fabf3a85ab88063c10f367cccba7b3a1e59df996 (patch) | |
tree | 7c1ea5590906e50359dd10c590a778f84abe3ca1 /net | |
parent | a8b563894d6fee9b90b7d6ed76f8ec28ad45bcbe (diff) |
netfilter: xt_statistic: remove nth_lock spinlock
Use atomic_cmpxchg() to avoid dirtying a shared location.
xt_statistic_priv smp aligned to avoid sharing same cache line with
other stuff.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/xt_statistic.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c index 96e62b8fd6b1..42ecb71d445f 100644 --- a/net/netfilter/xt_statistic.c +++ b/net/netfilter/xt_statistic.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include <linux/netfilter/x_tables.h> | 18 | #include <linux/netfilter/x_tables.h> |
19 | 19 | ||
20 | struct xt_statistic_priv { | 20 | struct xt_statistic_priv { |
21 | uint32_t count; | 21 | atomic_t count; |
22 | }; | 22 | } ____cacheline_aligned_in_smp; |
23 | 23 | ||
24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
25 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 25 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
@@ -27,13 +27,12 @@ MODULE_DESCRIPTION("Xtables: statistics-based matching (\"Nth\", random)"); | |||
27 | MODULE_ALIAS("ipt_statistic"); | 27 | MODULE_ALIAS("ipt_statistic"); |
28 | MODULE_ALIAS("ip6t_statistic"); | 28 | MODULE_ALIAS("ip6t_statistic"); |
29 | 29 | ||
30 | static DEFINE_SPINLOCK(nth_lock); | ||
31 | |||
32 | static bool | 30 | static bool |
33 | statistic_mt(const struct sk_buff *skb, struct xt_action_param *par) | 31 | statistic_mt(const struct sk_buff *skb, struct xt_action_param *par) |
34 | { | 32 | { |
35 | const struct xt_statistic_info *info = par->matchinfo; | 33 | const struct xt_statistic_info *info = par->matchinfo; |
36 | bool ret = info->flags & XT_STATISTIC_INVERT; | 34 | bool ret = info->flags & XT_STATISTIC_INVERT; |
35 | int nval, oval; | ||
37 | 36 | ||
38 | switch (info->mode) { | 37 | switch (info->mode) { |
39 | case XT_STATISTIC_MODE_RANDOM: | 38 | case XT_STATISTIC_MODE_RANDOM: |
@@ -41,12 +40,12 @@ statistic_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
41 | ret = !ret; | 40 | ret = !ret; |
42 | break; | 41 | break; |
43 | case XT_STATISTIC_MODE_NTH: | 42 | case XT_STATISTIC_MODE_NTH: |
44 | spin_lock_bh(&nth_lock); | 43 | do { |
45 | if (info->master->count++ == info->u.nth.every) { | 44 | oval = atomic_read(&info->master->count); |
46 | info->master->count = 0; | 45 | nval = (oval == info->u.nth.every) ? 0 : oval + 1; |
46 | } while (atomic_cmpxchg(&info->master->count, oval, nval) != oval); | ||
47 | if (nval == 0) | ||
47 | ret = !ret; | 48 | ret = !ret; |
48 | } | ||
49 | spin_unlock_bh(&nth_lock); | ||
50 | break; | 49 | break; |
51 | } | 50 | } |
52 | 51 | ||
@@ -64,7 +63,7 @@ static int statistic_mt_check(const struct xt_mtchk_param *par) | |||
64 | info->master = kzalloc(sizeof(*info->master), GFP_KERNEL); | 63 | info->master = kzalloc(sizeof(*info->master), GFP_KERNEL); |
65 | if (info->master == NULL) | 64 | if (info->master == NULL) |
66 | return -ENOMEM; | 65 | return -ENOMEM; |
67 | info->master->count = info->u.nth.count; | 66 | atomic_set(&info->master->count, info->u.nth.count); |
68 | 67 | ||
69 | return 0; | 68 | return 0; |
70 | } | 69 | } |