diff options
| author | David S. Miller <davem@davemloft.net> | 2010-08-25 05:27:49 -0400 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-08-25 05:27:49 -0400 | 
| commit | ad1af0fedba14f82b240a03fe20eb9b2fdbd0357 (patch) | |
| tree | 4d53aa8bc2d9df782aa792e52670ab55c7a44d5b /include/net/tcp.h | |
| parent | b2bc85631e72485b984bcd202a104591874babba (diff) | |
tcp: Combat per-cpu skew in orphan tests.
As reported by Anton Blanchard when we use
percpu_counter_read_positive() to make our orphan socket limit checks,
the check can be off by up to num_cpus_online() * batch (which is 32
by default) which on a 128 cpu machine can be as large as the default
orphan limit itself.
Fix this by doing the full expensive sum check if the optimized check
triggers.
Reported-by: Anton Blanchard <anton@samba.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Diffstat (limited to 'include/net/tcp.h')
| -rw-r--r-- | include/net/tcp.h | 18 | 
1 files changed, 14 insertions, 4 deletions
| diff --git a/include/net/tcp.h b/include/net/tcp.h index df6a2eb20193..eaa9582779d0 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
| @@ -268,11 +268,21 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3) | |||
| 268 | return seq3 - seq2 >= seq1 - seq2; | 268 | return seq3 - seq2 >= seq1 - seq2; | 
| 269 | } | 269 | } | 
| 270 | 270 | ||
| 271 | static inline int tcp_too_many_orphans(struct sock *sk, int num) | 271 | static inline bool tcp_too_many_orphans(struct sock *sk, int shift) | 
| 272 | { | 272 | { | 
| 273 | return (num > sysctl_tcp_max_orphans) || | 273 | struct percpu_counter *ocp = sk->sk_prot->orphan_count; | 
| 274 | (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && | 274 | int orphans = percpu_counter_read_positive(ocp); | 
| 275 | atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]); | 275 | |
| 276 | if (orphans << shift > sysctl_tcp_max_orphans) { | ||
| 277 | orphans = percpu_counter_sum_positive(ocp); | ||
| 278 | if (orphans << shift > sysctl_tcp_max_orphans) | ||
| 279 | return true; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && | ||
| 283 | atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]) | ||
| 284 | return true; | ||
| 285 | return false; | ||
| 276 | } | 286 | } | 
| 277 | 287 | ||
| 278 | /* syncookies: remember time of last synqueue overflow */ | 288 | /* syncookies: remember time of last synqueue overflow */ | 
