@@ -408,27 +408,20 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
408408}
409409EXPORT_SYMBOL (skb_kill_datagram );
410410
411- /**
412- * skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
413- * @skb: buffer to copy
414- * @offset: offset in the buffer to start copying from
415- * @to: iovec iterator to copy to
416- * @len: amount of data to copy from buffer to iovec
417- */
418- int skb_copy_datagram_iter (const struct sk_buff * skb , int offset ,
419- struct iov_iter * to , int len )
411+ int __skb_datagram_iter (const struct sk_buff * skb , int offset ,
412+ struct iov_iter * to , int len , bool fault_short ,
413+ size_t (* cb )(const void * , size_t , void * , struct iov_iter * ),
414+ void * data )
420415{
421416 int start = skb_headlen (skb );
422417 int i , copy = start - offset , start_off = offset , n ;
423418 struct sk_buff * frag_iter ;
424419
425- trace_skb_copy_datagram_iovec (skb , len );
426-
427420 /* Copy header. */
428421 if (copy > 0 ) {
429422 if (copy > len )
430423 copy = len ;
431- n = copy_to_iter (skb -> data + offset , copy , to );
424+ n = cb (skb -> data + offset , copy , data , to );
432425 offset += n ;
433426 if (n != copy )
434427 goto short_copy ;
@@ -450,8 +443,8 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
450443
451444 if (copy > len )
452445 copy = len ;
453- n = copy_to_iter (vaddr + frag -> page_offset +
454- offset - start , copy , to );
446+ n = cb (vaddr + frag -> page_offset +
447+ offset - start , copy , data , to );
455448 kunmap (page );
456449 offset += n ;
457450 if (n != copy )
@@ -471,8 +464,8 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
471464 if ((copy = end - offset ) > 0 ) {
472465 if (copy > len )
473466 copy = len ;
474- if (skb_copy_datagram_iter (frag_iter , offset - start ,
475- to , copy ))
467+ if (__skb_datagram_iter (frag_iter , offset - start ,
468+ to , copy , short_copy , cb , data ))
476469 goto fault ;
477470 if ((len -= copy ) == 0 )
478471 return 0 ;
@@ -493,11 +486,32 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
493486 return - EFAULT ;
494487
495488short_copy :
496- if (iov_iter_count (to ))
489+ if (fault_short || iov_iter_count (to ))
497490 goto fault ;
498491
499492 return 0 ;
500493}
494+
495+ static size_t simple_copy_to_iter (const void * addr , size_t bytes ,
496+ void * data __always_unused , struct iov_iter * i )
497+ {
498+ return copy_to_iter (addr , bytes , i );
499+ }
500+
501+ /**
502+ * skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
503+ * @skb: buffer to copy
504+ * @offset: offset in the buffer to start copying from
505+ * @to: iovec iterator to copy to
506+ * @len: amount of data to copy from buffer to iovec
507+ */
508+ int skb_copy_datagram_iter (const struct sk_buff * skb , int offset ,
509+ struct iov_iter * to , int len )
510+ {
511+ trace_skb_copy_datagram_iovec (skb , len );
512+ return __skb_datagram_iter (skb , offset , to , len , false,
513+ simple_copy_to_iter , NULL );
514+ }
501515EXPORT_SYMBOL (skb_copy_datagram_iter );
502516
503517/**
@@ -648,87 +662,21 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
648662}
649663EXPORT_SYMBOL (zerocopy_sg_from_iter );
650664
665+ /**
666+ * skb_copy_and_csum_datagram_iter - Copy datagram to an iovec iterator
667+ * and update a checksum.
668+ * @skb: buffer to copy
669+ * @offset: offset in the buffer to start copying from
670+ * @to: iovec iterator to copy to
671+ * @len: amount of data to copy from buffer to iovec
672+ * @csump: checksum pointer
673+ */
651674static int skb_copy_and_csum_datagram (const struct sk_buff * skb , int offset ,
652675 struct iov_iter * to , int len ,
653676 __wsum * csump )
654677{
655- int start = skb_headlen (skb );
656- int i , copy = start - offset , start_off = offset ;
657- struct sk_buff * frag_iter ;
658- int pos = 0 ;
659- int n ;
660-
661- /* Copy header. */
662- if (copy > 0 ) {
663- if (copy > len )
664- copy = len ;
665- n = csum_and_copy_to_iter (skb -> data + offset , copy , csump , to );
666- offset += n ;
667- if (n != copy )
668- goto fault ;
669- if ((len -= copy ) == 0 )
670- return 0 ;
671- pos = copy ;
672- }
673-
674- for (i = 0 ; i < skb_shinfo (skb )-> nr_frags ; i ++ ) {
675- int end ;
676- const skb_frag_t * frag = & skb_shinfo (skb )-> frags [i ];
677-
678- WARN_ON (start > offset + len );
679-
680- end = start + skb_frag_size (frag );
681- if ((copy = end - offset ) > 0 ) {
682- __wsum csum2 = 0 ;
683- struct page * page = skb_frag_page (frag );
684- u8 * vaddr = kmap (page );
685-
686- if (copy > len )
687- copy = len ;
688- n = csum_and_copy_to_iter (vaddr + frag -> page_offset +
689- offset - start , copy ,
690- & csum2 , to );
691- kunmap (page );
692- offset += n ;
693- if (n != copy )
694- goto fault ;
695- * csump = csum_block_add (* csump , csum2 , pos );
696- if (!(len -= copy ))
697- return 0 ;
698- pos += copy ;
699- }
700- start = end ;
701- }
702-
703- skb_walk_frags (skb , frag_iter ) {
704- int end ;
705-
706- WARN_ON (start > offset + len );
707-
708- end = start + frag_iter -> len ;
709- if ((copy = end - offset ) > 0 ) {
710- __wsum csum2 = 0 ;
711- if (copy > len )
712- copy = len ;
713- if (skb_copy_and_csum_datagram (frag_iter ,
714- offset - start ,
715- to , copy ,
716- & csum2 ))
717- goto fault ;
718- * csump = csum_block_add (* csump , csum2 , pos );
719- if ((len -= copy ) == 0 )
720- return 0 ;
721- offset += copy ;
722- pos += copy ;
723- }
724- start = end ;
725- }
726- if (!len )
727- return 0 ;
728-
729- fault :
730- iov_iter_revert (to , offset - start_off );
731- return - EFAULT ;
678+ return __skb_datagram_iter (skb , offset , to , len , true,
679+ csum_and_copy_to_iter , csump );
732680}
733681
734682__sum16 __skb_checksum_complete_head (struct sk_buff * skb , int len )
0 commit comments