@ -103,7 +103,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
struct iov_iter iov_iter ;
unsigned out , in ;
size_t nbytes ;
size_t len ;
size_t iov_len , payload_ len;
int head ;
spin_lock_bh ( & vsock - > send_pkt_list_lock ) ;
@ -148,8 +148,24 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
break ;
}
len = iov_length ( & vq - > iov [ out ] , in ) ;
iov_iter_init ( & iov_iter , READ , & vq - > iov [ out ] , in , len ) ;
iov_len = iov_length ( & vq - > iov [ out ] , in ) ;
if ( iov_len < sizeof ( pkt - > hdr ) ) {
virtio_transport_free_pkt ( pkt ) ;
vq_err ( vq , " Buffer len [%zu] too small \n " , iov_len ) ;
break ;
}
iov_iter_init ( & iov_iter , READ , & vq - > iov [ out ] , in , iov_len ) ;
payload_len = pkt - > len - pkt - > off ;
/* If the packet is greater than the space available in the
* buffer , we split it using multiple buffers .
*/
if ( payload_len > iov_len - sizeof ( pkt - > hdr ) )
payload_len = iov_len - sizeof ( pkt - > hdr ) ;
/* Set the correct length in the header */
pkt - > hdr . len = cpu_to_le32 ( payload_len ) ;
nbytes = copy_to_iter ( & pkt - > hdr , sizeof ( pkt - > hdr ) , & iov_iter ) ;
if ( nbytes ! = sizeof ( pkt - > hdr ) ) {
@ -158,33 +174,47 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
break ;
}
nbytes = copy_to_iter ( pkt - > buf , pkt - > len , & iov_iter ) ;
if ( nbytes ! = pkt - > len ) {
nbytes = copy_to_iter ( pkt - > buf + pkt - > off , payload_len ,
& iov_iter ) ;
if ( nbytes ! = payload_len ) {
virtio_transport_free_pkt ( pkt ) ;
vq_err ( vq , " Faulted on copying pkt buf \n " ) ;
break ;
}
vhost_add_used ( vq , head , sizeof ( pkt - > hdr ) + pkt - > len ) ;
vhost_add_used ( vq , head , sizeof ( pkt - > hdr ) + payload_ len ) ;
added = true ;
if ( pkt - > reply ) {
int val ;
val = atomic_dec_return ( & vsock - > queued_replies ) ;
/* Do we have resources to resume tx processing? */
if ( val + 1 = = tx_vq - > num )
restart_tx = true ;
}
/* Deliver to monitoring devices all correctly transmitted
* packets .
*/
virtio_transport_deliver_tap_pkt ( pkt ) ;
total_len + = pkt - > len ;
virtio_transport_free_pkt ( pkt ) ;
pkt - > off + = payload_len ;
total_len + = payload_len ;
/* If we didn't send all the payload we can requeue the packet
* to send it with the next available buffer .
*/
if ( pkt - > off < pkt - > len ) {
spin_lock_bh ( & vsock - > send_pkt_list_lock ) ;
list_add ( & pkt - > list , & vsock - > send_pkt_list ) ;
spin_unlock_bh ( & vsock - > send_pkt_list_lock ) ;
} else {
if ( pkt - > reply ) {
int val ;
val = atomic_dec_return ( & vsock - > queued_replies ) ;
/* Do we have resources to resume tx
* processing ?
*/
if ( val + 1 = = tx_vq - > num )
restart_tx = true ;
}
virtio_transport_free_pkt ( pkt ) ;
}
} while ( likely ( ! vhost_exceeds_weight ( vq , + + pkts , total_len ) ) ) ;
if ( added )
vhost_signal ( & vsock - > dev , vq ) ;