@@ -929,6 +929,51 @@ static struct net_iov *io_zcrx_alloc_fallback(struct io_zcrx_area *area)
929929 return niov ;
930930}
931931
932+ struct io_copy_cache {
933+ struct page * page ;
934+ unsigned long offset ;
935+ size_t size ;
936+ };
937+
938+ static ssize_t io_copy_page (struct io_copy_cache * cc , struct page * src_page ,
939+ unsigned int src_offset , size_t len )
940+ {
941+ size_t copied = 0 ;
942+
943+ len = min (len , cc -> size );
944+
945+ while (len ) {
946+ void * src_addr , * dst_addr ;
947+ struct page * dst_page = cc -> page ;
948+ unsigned dst_offset = cc -> offset ;
949+ size_t n = len ;
950+
951+ if (folio_test_partial_kmap (page_folio (dst_page )) ||
952+ folio_test_partial_kmap (page_folio (src_page ))) {
953+ dst_page = nth_page (dst_page , dst_offset / PAGE_SIZE );
954+ dst_offset = offset_in_page (dst_offset );
955+ src_page = nth_page (src_page , src_offset / PAGE_SIZE );
956+ src_offset = offset_in_page (src_offset );
957+ n = min (PAGE_SIZE - src_offset , PAGE_SIZE - dst_offset );
958+ n = min (n , len );
959+ }
960+
961+ dst_addr = kmap_local_page (dst_page ) + dst_offset ;
962+ src_addr = kmap_local_page (src_page ) + src_offset ;
963+
964+ memcpy (dst_addr , src_addr , n );
965+
966+ kunmap_local (src_addr );
967+ kunmap_local (dst_addr );
968+
969+ cc -> size -= n ;
970+ cc -> offset += n ;
971+ len -= n ;
972+ copied += n ;
973+ }
974+ return copied ;
975+ }
976+
932977static ssize_t io_zcrx_copy_chunk (struct io_kiocb * req , struct io_zcrx_ifq * ifq ,
933978 struct page * src_page , unsigned int src_offset ,
934979 size_t len )
@@ -941,37 +986,32 @@ static ssize_t io_zcrx_copy_chunk(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
941986 return - EFAULT ;
942987
943988 while (len ) {
944- size_t copy_size = min_t (size_t , PAGE_SIZE , len );
945- const int dst_off = 0 ;
989+ struct io_copy_cache cc ;
946990 struct net_iov * niov ;
947- struct page * dst_page ;
948- void * dst_addr , * src_addr ;
991+ size_t n ;
949992
950993 niov = io_zcrx_alloc_fallback (area );
951994 if (!niov ) {
952995 ret = - ENOMEM ;
953996 break ;
954997 }
955998
956- dst_page = io_zcrx_iov_page (niov );
957- dst_addr = kmap_local_page (dst_page );
958- src_addr = kmap_local_page (src_page );
959-
960- memcpy (dst_addr , src_addr + src_offset , copy_size );
999+ cc .page = io_zcrx_iov_page (niov );
1000+ cc .offset = 0 ;
1001+ cc .size = PAGE_SIZE ;
9611002
962- kunmap_local (src_addr );
963- kunmap_local (dst_addr );
1003+ n = io_copy_page (& cc , src_page , src_offset , len );
9641004
965- if (!io_zcrx_queue_cqe (req , niov , ifq , dst_off , copy_size )) {
1005+ if (!io_zcrx_queue_cqe (req , niov , ifq , 0 , n )) {
9661006 io_zcrx_return_niov (niov );
9671007 ret = - ENOSPC ;
9681008 break ;
9691009 }
9701010
9711011 io_zcrx_get_niov_uref (niov );
972- src_offset += copy_size ;
973- len -= copy_size ;
974- copied += copy_size ;
1012+ src_offset += n ;
1013+ len -= n ;
1014+ copied += n ;
9751015 }
9761016
9771017 return copied ? copied : ret ;
@@ -981,19 +1021,8 @@ static int io_zcrx_copy_frag(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
9811021 const skb_frag_t * frag , int off , int len )
9821022{
9831023 struct page * page = skb_frag_page (frag );
984- u32 p_off , p_len , t , copied = 0 ;
985- int ret = 0 ;
9861024
987- off += skb_frag_off (frag );
988-
989- skb_frag_foreach_page (frag , off , len ,
990- page , p_off , p_len , t ) {
991- ret = io_zcrx_copy_chunk (req , ifq , page , p_off , p_len );
992- if (ret < 0 )
993- return copied ? copied : ret ;
994- copied += ret ;
995- }
996- return copied ;
1025+ return io_zcrx_copy_chunk (req , ifq , page , off + skb_frag_off (frag ), len );
9971026}
9981027
9991028static int io_zcrx_recv_frag (struct io_kiocb * req , struct io_zcrx_ifq * ifq ,
0 commit comments