| From b6bd33114e63d96f424c8e2baf46b3a58745077b Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <eric.dumazet@gmail.com> |
| Date: Tue, 7 Dec 2010 12:03:55 +0000 |
| Subject: tcp: avoid a possible divide by zero |
| |
| |
| From: Eric Dumazet <eric.dumazet@gmail.com> |
| |
| [ Upstream commit ad9f4f50fe9288bbe65b7dfd76d8820afac6a24c ] |
| |
| sysctl_tcp_tso_win_divisor might be set to zero while one cpu runs in |
| tcp_tso_should_defer(). Make sure we dont allow a divide by zero by |
| reading sysctl_tcp_tso_win_divisor exactly once. |
| |
| Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| net/ipv4/tcp_output.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/net/ipv4/tcp_output.c |
| +++ b/net/ipv4/tcp_output.c |
| @@ -1518,6 +1518,7 @@ static int tcp_tso_should_defer(struct s |
| struct tcp_sock *tp = tcp_sk(sk); |
| const struct inet_connection_sock *icsk = inet_csk(sk); |
| u32 send_win, cong_win, limit, in_flight; |
| + int win_divisor; |
| |
| if (TCP_SKB_CB(skb)->flags & TCPHDR_FIN) |
| goto send_now; |
| @@ -1549,13 +1550,14 @@ static int tcp_tso_should_defer(struct s |
| if ((skb != tcp_write_queue_tail(sk)) && (limit >= skb->len)) |
| goto send_now; |
| |
| - if (sysctl_tcp_tso_win_divisor) { |
| + win_divisor = ACCESS_ONCE(sysctl_tcp_tso_win_divisor); |
| + if (win_divisor) { |
| u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); |
| |
| /* If at least some fraction of a window is available, |
| * just use it. |
| */ |
| - chunk /= sysctl_tcp_tso_win_divisor; |
| + chunk /= win_divisor; |
| if (limit >= chunk) |
| goto send_now; |
| } else { |