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 /net/ipv4/tcp_timer.c | |
| 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 'net/ipv4/tcp_timer.c')
| -rw-r--r-- | net/ipv4/tcp_timer.c | 8 | 
1 files changed, 4 insertions, 4 deletions
| diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 808bb920c9f5..c35b469e851c 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
| @@ -66,18 +66,18 @@ static void tcp_write_err(struct sock *sk) | |||
| 66 | static int tcp_out_of_resources(struct sock *sk, int do_reset) | 66 | static int tcp_out_of_resources(struct sock *sk, int do_reset) | 
| 67 | { | 67 | { | 
| 68 | struct tcp_sock *tp = tcp_sk(sk); | 68 | struct tcp_sock *tp = tcp_sk(sk); | 
| 69 | int orphans = percpu_counter_read_positive(&tcp_orphan_count); | 69 | int shift = 0; | 
| 70 | 70 | ||
| 71 | /* If peer does not open window for long time, or did not transmit | 71 | /* If peer does not open window for long time, or did not transmit | 
| 72 | * anything for long time, penalize it. */ | 72 | * anything for long time, penalize it. */ | 
| 73 | if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset) | 73 | if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset) | 
| 74 | orphans <<= 1; | 74 | shift++; | 
| 75 | 75 | ||
| 76 | /* If some dubious ICMP arrived, penalize even more. */ | 76 | /* If some dubious ICMP arrived, penalize even more. */ | 
| 77 | if (sk->sk_err_soft) | 77 | if (sk->sk_err_soft) | 
| 78 | orphans <<= 1; | 78 | shift++; | 
| 79 | 79 | ||
| 80 | if (tcp_too_many_orphans(sk, orphans)) { | 80 | if (tcp_too_many_orphans(sk, shift)) { | 
| 81 | if (net_ratelimit()) | 81 | if (net_ratelimit()) | 
| 82 | printk(KERN_INFO "Out of socket memory\n"); | 82 | printk(KERN_INFO "Out of socket memory\n"); | 
| 83 | 83 | ||
