diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
| -rw-r--r-- | net/ipv6/ip6_output.c | 19 | 
1 files changed, 19 insertions, 0 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9554cf46ed88..1e8c90e97608 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -42,6 +42,7 @@  #include <net/sock.h>  #include <net/snmp.h> +#include <net/gso.h>  #include <net/ipv6.h>  #include <net/ndisc.h>  #include <net/protocol.h> @@ -1589,6 +1590,15 @@ emsgsize:  				skb_zcopy_set(skb, uarg, &extra_uref);  			}  		} +	} else if ((flags & MSG_SPLICE_PAGES) && length) { +		if (inet_sk(sk)->hdrincl) +			return -EPERM; +		if (rt->dst.dev->features & NETIF_F_SG && +		    getfrag == ip_generic_getfrag) +			/* We need an empty buffer to attach stuff to */ +			paged = true; +		else +			flags &= ~MSG_SPLICE_PAGES;  	}  	/* @@ -1778,6 +1788,15 @@ alloc_new_skb:  				err = -EFAULT;  				goto error;  			} +		} else if (flags & MSG_SPLICE_PAGES) { +			struct msghdr *msg = from; + +			err = skb_splice_from_iter(skb, &msg->msg_iter, copy, +						   sk->sk_allocation); +			if (err < 0) +				goto error; +			copy = err; +			wmem_alloc_delta += copy;  		} else if (!zc) {  			int i = skb_shinfo(skb)->nr_frags;  |