diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
| -rw-r--r-- | net/ipv4/tcp_output.c | 15 | 
1 files changed, 12 insertions, 3 deletions
| diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 03d26b85eab8..3be16727f058 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -698,7 +698,8 @@ static void tcp_tsq_handler(struct sock *sk)  	if ((1 << sk->sk_state) &  	    (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_CLOSING |  	     TCPF_CLOSE_WAIT  | TCPF_LAST_ACK)) -		tcp_write_xmit(sk, tcp_current_mss(sk), 0, 0, GFP_ATOMIC); +		tcp_write_xmit(sk, tcp_current_mss(sk), tcp_sk(sk)->nonagle, +			       0, GFP_ATOMIC);  }  /*   * One tasklet per cpu tries to send more skbs. @@ -1904,7 +1905,15 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,  		if (atomic_read(&sk->sk_wmem_alloc) > limit) {  			set_bit(TSQ_THROTTLED, &tp->tsq_flags); -			break; +			/* It is possible TX completion already happened +			 * before we set TSQ_THROTTLED, so we must +			 * test again the condition. +			 * We abuse smp_mb__after_clear_bit() because +			 * there is no smp_mb__after_set_bit() yet +			 */ +			smp_mb__after_clear_bit(); +			if (atomic_read(&sk->sk_wmem_alloc) > limit) +				break;  		}  		limit = mss_now; @@ -1977,7 +1986,7 @@ bool tcp_schedule_loss_probe(struct sock *sk)  	/* Schedule a loss probe in 2*RTT for SACK capable connections  	 * in Open state, that are either limited by cwnd or application.  	 */ -	if (sysctl_tcp_early_retrans < 3 || !rtt || !tp->packets_out || +	if (sysctl_tcp_early_retrans < 3 || !tp->srtt || !tp->packets_out ||  	    !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open)  		return false; | 
