| From a84559e539b2ae157c435ba155d4c39d4b4ce28c Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <eric.dumazet@gmail.com> |
| Date: Tue, 7 Dec 2010 12:03:55 +0000 |
| Subject: [PATCH] tcp: avoid a possible divide by zero |
| |
| commit ad9f4f50fe9288bbe65b7dfd76d8820afac6a24c upstream |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c |
| index e1819aa..6fdff30 100644 |
| --- a/net/ipv4/tcp_output.c |
| +++ b/net/ipv4/tcp_output.c |
| @@ -1514,6 +1514,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) |
| 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 & TCPCB_FLAG_FIN) |
| goto send_now; |
| @@ -1545,13 +1546,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) |
| 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 { |
| -- |
| 1.7.4.4 |
| |