diff options
Diffstat (limited to 'net/ipv4/tcp.c')
| -rw-r--r-- | net/ipv4/tcp.c | 25 | 
1 files changed, 14 insertions, 11 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index e457c7ab2e2..1ca253635f7 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -536,13 +536,14 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)  {  	struct tcp_sock *tp = tcp_sk(sk);  	int answ; +	bool slow;  	switch (cmd) {  	case SIOCINQ:  		if (sk->sk_state == TCP_LISTEN)  			return -EINVAL; -		lock_sock(sk); +		slow = lock_sock_fast(sk);  		if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))  			answ = 0;  		else if (sock_flag(sk, SOCK_URGINLINE) || @@ -557,7 +558,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)  				answ--;  		} else  			answ = tp->urg_seq - tp->copied_seq; -		release_sock(sk); +		unlock_sock_fast(sk, slow);  		break;  	case SIOCATMARK:  		answ = tp->urg_data && tp->urg_seq == tp->copied_seq; @@ -1490,15 +1491,19 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,  				copied += used;  				offset += used;  			} -			/* -			 * If recv_actor drops the lock (e.g. TCP splice +			/* If recv_actor drops the lock (e.g. TCP splice  			 * receive) the skb pointer might be invalid when  			 * getting here: tcp_collapse might have deleted it  			 * while aggregating skbs from the socket queue.  			 */ -			skb = tcp_recv_skb(sk, seq-1, &offset); -			if (!skb || (offset+1 != skb->len)) +			skb = tcp_recv_skb(sk, seq - 1, &offset); +			if (!skb)  				break; +			/* TCP coalescing might have appended data to the skb. +			 * Try to splice more frags +			 */ +			if (offset + 1 != skb->len) +				continue;  		}  		if (tcp_hdr(skb)->fin) {  			sk_eat_skb(sk, skb, false); @@ -2300,7 +2305,7 @@ void tcp_sock_destruct(struct sock *sk)  static inline bool tcp_can_repair_sock(const struct sock *sk)  { -	return capable(CAP_NET_ADMIN) && +	return ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN) &&  		((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));  } @@ -3586,8 +3591,7 @@ void __init tcp_init(void)  		alloc_large_system_hash("TCP established",  					sizeof(struct inet_ehash_bucket),  					thash_entries, -					(totalram_pages >= 128 * 1024) ? -					13 : 15, +					17, /* one slot per 128 KB of memory */  					0,  					NULL,  					&tcp_hashinfo.ehash_mask, @@ -3603,8 +3607,7 @@ void __init tcp_init(void)  		alloc_large_system_hash("TCP bind",  					sizeof(struct inet_bind_hashbucket),  					tcp_hashinfo.ehash_mask + 1, -					(totalram_pages >= 128 * 1024) ? -					13 : 15, +					17, /* one slot per 128 KB of memory */  					0,  					&tcp_hashinfo.bhash_size,  					NULL,  |