@@ -572,6 +572,78 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
572
572
}
573
573
EXPORT_SYMBOL (skb_copy_datagram_from_iovec );
574
574
575
+ int skb_copy_datagram_from_iter (struct sk_buff * skb , int offset ,
576
+ struct iov_iter * from ,
577
+ int len )
578
+ {
579
+ int start = skb_headlen (skb );
580
+ int i , copy = start - offset ;
581
+ struct sk_buff * frag_iter ;
582
+
583
+ /* Copy header. */
584
+ if (copy > 0 ) {
585
+ if (copy > len )
586
+ copy = len ;
587
+ if (copy_from_iter (skb -> data + offset , copy , from ) != copy )
588
+ goto fault ;
589
+ if ((len -= copy ) == 0 )
590
+ return 0 ;
591
+ offset += copy ;
592
+ }
593
+
594
+ /* Copy paged appendix. Hmm... why does this look so complicated? */
595
+ for (i = 0 ; i < skb_shinfo (skb )-> nr_frags ; i ++ ) {
596
+ int end ;
597
+ const skb_frag_t * frag = & skb_shinfo (skb )-> frags [i ];
598
+
599
+ WARN_ON (start > offset + len );
600
+
601
+ end = start + skb_frag_size (frag );
602
+ if ((copy = end - offset ) > 0 ) {
603
+ size_t copied ;
604
+
605
+ if (copy > len )
606
+ copy = len ;
607
+ copied = copy_page_from_iter (skb_frag_page (frag ),
608
+ frag -> page_offset + offset - start ,
609
+ copy , from );
610
+ if (copied != copy )
611
+ goto fault ;
612
+
613
+ if (!(len -= copy ))
614
+ return 0 ;
615
+ offset += copy ;
616
+ }
617
+ start = end ;
618
+ }
619
+
620
+ skb_walk_frags (skb , frag_iter ) {
621
+ int end ;
622
+
623
+ WARN_ON (start > offset + len );
624
+
625
+ end = start + frag_iter -> len ;
626
+ if ((copy = end - offset ) > 0 ) {
627
+ if (copy > len )
628
+ copy = len ;
629
+ if (skb_copy_datagram_from_iter (frag_iter ,
630
+ offset - start ,
631
+ from , copy ))
632
+ goto fault ;
633
+ if ((len -= copy ) == 0 )
634
+ return 0 ;
635
+ offset += copy ;
636
+ }
637
+ start = end ;
638
+ }
639
+ if (!len )
640
+ return 0 ;
641
+
642
+ fault :
643
+ return - EFAULT ;
644
+ }
645
+ EXPORT_SYMBOL (skb_copy_datagram_from_iter );
646
+
575
647
/**
576
648
* zerocopy_sg_from_iovec - Build a zerocopy datagram from an iovec
577
649
* @skb: buffer to copy
@@ -643,6 +715,50 @@ int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
643
715
}
644
716
EXPORT_SYMBOL (zerocopy_sg_from_iovec );
645
717
718
+ int zerocopy_sg_from_iter (struct sk_buff * skb , struct iov_iter * from )
719
+ {
720
+ int len = iov_iter_count (from );
721
+ int copy = min_t (int , skb_headlen (skb ), len );
722
+ int frag = 0 ;
723
+
724
+ /* copy up to skb headlen */
725
+ if (skb_copy_datagram_from_iter (skb , 0 , from , copy ))
726
+ return - EFAULT ;
727
+
728
+ while (iov_iter_count (from )) {
729
+ struct page * pages [MAX_SKB_FRAGS ];
730
+ size_t start ;
731
+ ssize_t copied ;
732
+ unsigned long truesize ;
733
+ int n = 0 ;
734
+
735
+ if (frag == MAX_SKB_FRAGS )
736
+ return - EMSGSIZE ;
737
+
738
+ copied = iov_iter_get_pages (from , pages , ~0U ,
739
+ MAX_SKB_FRAGS - frag , & start );
740
+ if (copied < 0 )
741
+ return - EFAULT ;
742
+
743
+ iov_iter_advance (from , copied );
744
+
745
+ truesize = PAGE_ALIGN (copied + start );
746
+ skb -> data_len += copied ;
747
+ skb -> len += copied ;
748
+ skb -> truesize += truesize ;
749
+ atomic_add (truesize , & skb -> sk -> sk_wmem_alloc );
750
+ while (copied ) {
751
+ int size = min_t (int , copied , PAGE_SIZE - start );
752
+ skb_fill_page_desc (skb , frag ++ , pages [n ], start , size );
753
+ start = 0 ;
754
+ copied -= size ;
755
+ n ++ ;
756
+ }
757
+ }
758
+ return 0 ;
759
+ }
760
+ EXPORT_SYMBOL (zerocopy_sg_from_iter );
761
+
646
762
static int skb_copy_and_csum_datagram (const struct sk_buff * skb , int offset ,
647
763
u8 __user * to , int len ,
648
764
__wsum * csump )
0 commit comments