@ -49,6 +49,7 @@
# include <linux/spinlock.h>
# include <linux/slab.h>
# include <linux/pagemap.h>
# include <linux/uio.h>
# include <net/protocol.h>
# include <linux/skbuff.h>
@ -481,6 +482,92 @@ fault:
}
EXPORT_SYMBOL ( skb_copy_datagram_const_iovec ) ;
/**
* skb_copy_datagram_iter - Copy a datagram to an iovec iterator .
* @ skb : buffer to copy
* @ offset : offset in the buffer to start copying from
* @ to : iovec iterator to copy to
* @ len : amount of data to copy from buffer to iovec
*/
int skb_copy_datagram_iter ( const struct sk_buff * skb , int offset ,
struct iov_iter * to , int len )
{
int start = skb_headlen ( skb ) ;
int i , copy = start - offset ;
struct sk_buff * frag_iter ;
trace_skb_copy_datagram_iovec ( skb , len ) ;
/* Copy header. */
if ( copy > 0 ) {
if ( copy > len )
copy = len ;
if ( copy_to_iter ( skb - > data + offset , copy , to ) ! = copy )
goto short_copy ;
if ( ( len - = copy ) = = 0 )
return 0 ;
offset + = copy ;
}
/* Copy paged appendix. Hmm... why does this look so complicated? */
for ( i = 0 ; i < skb_shinfo ( skb ) - > nr_frags ; i + + ) {
int end ;
const skb_frag_t * frag = & skb_shinfo ( skb ) - > frags [ i ] ;
WARN_ON ( start > offset + len ) ;
end = start + skb_frag_size ( frag ) ;
if ( ( copy = end - offset ) > 0 ) {
if ( copy > len )
copy = len ;
if ( copy_page_to_iter ( skb_frag_page ( frag ) ,
frag - > page_offset + offset -
start , copy , to ) ! = copy )
goto short_copy ;
if ( ! ( len - = copy ) )
return 0 ;
offset + = copy ;
}
start = end ;
}
skb_walk_frags ( skb , frag_iter ) {
int end ;
WARN_ON ( start > offset + len ) ;
end = start + frag_iter - > len ;
if ( ( copy = end - offset ) > 0 ) {
if ( copy > len )
copy = len ;
if ( skb_copy_datagram_iter ( frag_iter , offset - start ,
to , copy ) )
goto fault ;
if ( ( len - = copy ) = = 0 )
return 0 ;
offset + = copy ;
}
start = end ;
}
if ( ! len )
return 0 ;
/* This is not really a user copy fault, but rather someone
* gave us a bogus length on the skb . We should probably
* print a warning here as it may indicate a kernel bug .
*/
fault :
return - EFAULT ;
short_copy :
if ( iov_iter_count ( to ) )
goto fault ;
return 0 ;
}
EXPORT_SYMBOL ( skb_copy_datagram_iter ) ;
/**
* skb_copy_datagram_from_iovec - Copy a datagram from an iovec .
* @ skb : buffer to copy