diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 16 | 
1 files changed, 9 insertions, 7 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 069642014636..27140e5cdc06 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -57,6 +57,7 @@  #include <linux/init.h>  #include <linux/times.h>  #include <linux/slab.h> +#include <linux/sched.h>  #include <net/net_namespace.h>  #include <net/icmp.h> @@ -312,7 +313,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)  					     inet->inet_daddr));  	} -	inet->inet_id = get_random_u16(); +	atomic_set(&inet->inet_id, get_random_u16());  	if (tcp_fastopen_defer_connect(sk, &err))  		return err; @@ -476,7 +477,6 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)  	const struct iphdr *iph = (const struct iphdr *)skb->data;  	struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));  	struct tcp_sock *tp; -	struct inet_sock *inet;  	const int type = icmp_hdr(skb)->type;  	const int code = icmp_hdr(skb)->code;  	struct sock *sk; @@ -624,8 +624,8 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)  	 *							--ANK (980905)  	 */ -	inet = inet_sk(sk); -	if (!sock_owned_by_user(sk) && inet->recverr) { +	if (!sock_owned_by_user(sk) && +	    inet_test_bit(RECVERR, sk)) {  		WRITE_ONCE(sk->sk_err, err);  		sk_error_report(sk);  	} else	{ /* Only an error on timeout */ @@ -931,9 +931,9 @@ static void tcp_v4_send_ack(const struct sock *sk,  	ctl_sk = this_cpu_read(ipv4_tcp_sk);  	sock_net_set(ctl_sk, net);  	ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ? -			   inet_twsk(sk)->tw_mark : sk->sk_mark; +			   inet_twsk(sk)->tw_mark : READ_ONCE(sk->sk_mark);  	ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ? -			   inet_twsk(sk)->tw_priority : sk->sk_priority; +			   inet_twsk(sk)->tw_priority : READ_ONCE(sk->sk_priority);  	transmit_time = tcp_transmit_time(sk);  	ip_send_unicast_reply(ctl_sk,  			      skb, &TCP_SKB_CB(skb)->header.h4.opt, @@ -1596,7 +1596,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,  	inet_csk(newsk)->icsk_ext_hdr_len = 0;  	if (inet_opt)  		inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; -	newinet->inet_id = get_random_u16(); +	atomic_set(&newinet->inet_id, get_random_u16());  	/* Set ToS of the new socket based upon the value of incoming SYN.  	 * ECT bits are set later in tcp_init_transfer(). @@ -2448,6 +2448,8 @@ static void *established_get_first(struct seq_file *seq)  		struct hlist_nulls_node *node;  		spinlock_t *lock = inet_ehash_lockp(hinfo, st->bucket); +		cond_resched(); +  		/* Lockless fast path for the common case of empty buckets */  		if (empty_bucket(hinfo, st))  			continue;  | 
