diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
| -rw-r--r-- | net/ipv4/af_inet.c | 84 | 
1 files changed, 66 insertions, 18 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 551ce564b03..6a1100c25a9 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -355,6 +355,8 @@ lookup_protocol:  	inet = inet_sk(sk);  	inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0; +	inet->nodefrag = 0; +  	if (SOCK_RAW == sock->type) {  		inet->inet_num = protocol;  		if (IPPROTO_RAW == protocol) @@ -725,28 +727,31 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,  	sock_rps_record_flow(sk);  	/* We may need to bind the socket. */ -	if (!inet_sk(sk)->inet_num && inet_autobind(sk)) +	if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind && +	    inet_autobind(sk))  		return -EAGAIN;  	return sk->sk_prot->sendmsg(iocb, sk, msg, size);  }  EXPORT_SYMBOL(inet_sendmsg); -static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, -			     size_t size, int flags) +ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, +		      size_t size, int flags)  {  	struct sock *sk = sock->sk;  	sock_rps_record_flow(sk);  	/* We may need to bind the socket. */ -	if (!inet_sk(sk)->inet_num && inet_autobind(sk)) +	if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind && +	    inet_autobind(sk))  		return -EAGAIN;  	if (sk->sk_prot->sendpage)  		return sk->sk_prot->sendpage(sk, page, offset, size, flags);  	return sock_no_sendpage(sock, page, offset, size, flags);  } +EXPORT_SYMBOL(inet_sendpage);  int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,  		 size_t size, int flags) @@ -892,10 +897,10 @@ const struct proto_ops inet_stream_ops = {  	.shutdown	   = inet_shutdown,  	.setsockopt	   = sock_common_setsockopt,  	.getsockopt	   = sock_common_getsockopt, -	.sendmsg	   = tcp_sendmsg, +	.sendmsg	   = inet_sendmsg,  	.recvmsg	   = inet_recvmsg,  	.mmap		   = sock_no_mmap, -	.sendpage	   = tcp_sendpage, +	.sendpage	   = inet_sendpage,  	.splice_read	   = tcp_splice_read,  #ifdef CONFIG_COMPAT  	.compat_setsockopt = compat_sock_common_setsockopt, @@ -1100,7 +1105,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)  	if (err)  		return err; -	sk_setup_caps(sk, &rt->u.dst); +	sk_setup_caps(sk, &rt->dst);  	new_saddr = rt->rt_src; @@ -1166,7 +1171,7 @@ int inet_sk_rebuild_header(struct sock *sk)  	err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0);  }  	if (!err) -		sk_setup_caps(sk, &rt->u.dst); +		sk_setup_caps(sk, &rt->dst);  	else {  		/* Routing failed... */  		sk->sk_route_caps = 0; @@ -1425,13 +1430,49 @@ unsigned long snmp_fold_field(void __percpu *mib[], int offt)  }  EXPORT_SYMBOL_GPL(snmp_fold_field); -int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) +#if BITS_PER_LONG==32 + +u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_offset) +{ +	u64 res = 0; +	int cpu; + +	for_each_possible_cpu(cpu) { +		void *bhptr, *userptr; +		struct u64_stats_sync *syncp; +		u64 v_bh, v_user; +		unsigned int start; + +		/* first mib used by softirq context, we must use _bh() accessors */ +		bhptr = per_cpu_ptr(SNMP_STAT_BHPTR(mib), cpu); +		syncp = (struct u64_stats_sync *)(bhptr + syncp_offset); +		do { +			start = u64_stats_fetch_begin_bh(syncp); +			v_bh = *(((u64 *) bhptr) + offt); +		} while (u64_stats_fetch_retry_bh(syncp, start)); + +		/* second mib used in USER context */ +		userptr = per_cpu_ptr(SNMP_STAT_USRPTR(mib), cpu); +		syncp = (struct u64_stats_sync *)(userptr + syncp_offset); +		do { +			start = u64_stats_fetch_begin(syncp); +			v_user = *(((u64 *) userptr) + offt); +		} while (u64_stats_fetch_retry(syncp, start)); + +		res += v_bh + v_user; +	} +	return res; +} +EXPORT_SYMBOL_GPL(snmp_fold_field64); +#endif + +int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align)  {  	BUG_ON(ptr == NULL); -	ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long)); +	ptr[0] = __alloc_percpu(mibsize, align);  	if (!ptr[0])  		goto err0; -	ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long)); +	ptr[1] = __alloc_percpu(mibsize, align);  	if (!ptr[1])  		goto err1;  	return 0; @@ -1488,25 +1529,32 @@ static const struct net_protocol icmp_protocol = {  static __net_init int ipv4_mib_init_net(struct net *net)  {  	if (snmp_mib_init((void __percpu **)net->mib.tcp_statistics, -			  sizeof(struct tcp_mib)) < 0) +			  sizeof(struct tcp_mib), +			  __alignof__(struct tcp_mib)) < 0)  		goto err_tcp_mib;  	if (snmp_mib_init((void __percpu **)net->mib.ip_statistics, -			  sizeof(struct ipstats_mib)) < 0) +			  sizeof(struct ipstats_mib), +			  __alignof__(struct ipstats_mib)) < 0)  		goto err_ip_mib;  	if (snmp_mib_init((void __percpu **)net->mib.net_statistics, -			  sizeof(struct linux_mib)) < 0) +			  sizeof(struct linux_mib), +			  __alignof__(struct linux_mib)) < 0)  		goto err_net_mib;  	if (snmp_mib_init((void __percpu **)net->mib.udp_statistics, -			  sizeof(struct udp_mib)) < 0) +			  sizeof(struct udp_mib), +			  __alignof__(struct udp_mib)) < 0)  		goto err_udp_mib;  	if (snmp_mib_init((void __percpu **)net->mib.udplite_statistics, -			  sizeof(struct udp_mib)) < 0) +			  sizeof(struct udp_mib), +			  __alignof__(struct udp_mib)) < 0)  		goto err_udplite_mib;  	if (snmp_mib_init((void __percpu **)net->mib.icmp_statistics, -			  sizeof(struct icmp_mib)) < 0) +			  sizeof(struct icmp_mib), +			  __alignof__(struct icmp_mib)) < 0)  		goto err_icmp_mib;  	if (snmp_mib_init((void __percpu **)net->mib.icmpmsg_statistics, -			  sizeof(struct icmpmsg_mib)) < 0) +			  sizeof(struct icmpmsg_mib), +			  __alignof__(struct icmpmsg_mib)) < 0)  		goto err_icmpmsg_mib;  	tcp_mib_init(net);  |