diff options
Diffstat (limited to 'net/ipv6/udp.c')
| -rw-r--r-- | net/ipv6/udp.c | 33 | 
1 files changed, 19 insertions, 14 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 75703fda23e7..4a3e65626e8b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -325,7 +325,7 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be  	sk =  __udp6_lib_lookup(net, saddr, sport, daddr, dport,  				dif, &udp_table, NULL); -	if (sk && !atomic_inc_not_zero(&sk->sk_refcnt)) +	if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))  		sk = NULL;  	return sk;  } @@ -362,7 +362,7 @@ try_again:  	if (!skb)  		return err; -	ulen = skb->len; +	ulen = udp_skb_len(skb);  	copied = len;  	if (copied > ulen - off)  		copied = ulen - off; @@ -379,14 +379,18 @@ try_again:  	if (copied < ulen || peeking ||  	    (is_udplite && UDP_SKB_CB(skb)->partial_cov)) { -		checksum_valid = !udp_lib_checksum_complete(skb); +		checksum_valid = udp_skb_csum_unnecessary(skb) || +				!__udp_lib_checksum_complete(skb);  		if (!checksum_valid)  			goto csum_copy_err;  	} -	if (checksum_valid || skb_csum_unnecessary(skb)) -		err = skb_copy_datagram_msg(skb, off, msg, copied); -	else { +	if (checksum_valid || udp_skb_csum_unnecessary(skb)) { +		if (udp_skb_is_linear(skb)) +			err = copy_linear_skb(skb, copied, off, &msg->msg_iter); +		else +			err = skb_copy_datagram_msg(skb, off, msg, copied); +	} else {  		err = skb_copy_and_csum_datagram_msg(skb, off, msg);  		if (err == -EINVAL)  			goto csum_copy_err; @@ -455,7 +459,8 @@ try_again:  	return err;  csum_copy_err: -	if (!__sk_queue_drop_skb(sk, skb, flags, udp_skb_destructor)) { +	if (!__sk_queue_drop_skb(sk, &udp_sk(sk)->reader_queue, skb, flags, +				 udp_skb_destructor)) {  		if (is_udp4) {  			UDP_INC_STATS(sock_net(sk),  				      UDP_MIB_CSUMERRORS, is_udplite); @@ -629,6 +634,7 @@ static int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)  		}  	} +	prefetch(&sk->sk_rmem_alloc);  	if (rcu_access_pointer(sk->sk_filter) &&  	    udp_lib_checksum_complete(skb))  		goto csum_error; @@ -910,7 +916,7 @@ static void udp_v6_early_demux(struct sk_buff *skb)  	else  		return; -	if (!sk || !atomic_inc_not_zero_hint(&sk->sk_refcnt, 2)) +	if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))  		return;  	skb->sk = sk; @@ -920,12 +926,11 @@ static void udp_v6_early_demux(struct sk_buff *skb)  	if (dst)  		dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);  	if (dst) { -		if (dst->flags & DST_NOCACHE) { -			if (likely(atomic_inc_not_zero(&dst->__refcnt))) -				skb_dst_set(skb, dst); -		} else { -			skb_dst_set_noref(skb, dst); -		} +		/* set noref for now. +		 * any place which wants to hold dst has to call +		 * dst_hold_safe() +		 */ +		skb_dst_set_noref(skb, dst);  	}  }  | 
