Skip to content

Commit 0df7cd3

Browse files
Arseniy KrasnovPaolo Abeni
authored andcommitted
vsock/virtio/vhost: read data from non-linear skb
This is preparation patch for MSG_ZEROCOPY support. It adds handling of non-linear skbs by replacing direct calls of 'memcpy_to_msg()' with 'skb_copy_datagram_iter()'. Main advantage of the second one is that it can handle paged part of the skb by using 'kmap()' on each page, but if there are no pages in the skb, it behaves like simple copying to iov iterator. This patch also adds new field to the control block of skb - this value shows current offset in the skb to read next portion of data (it doesn't matter linear it or not). Idea behind this field is that 'skb_copy_datagram_iter()' handles both types of skb internally - it just needs an offset from which to copy data from the given skb. This offset is incremented on each read from skb. This approach allows to simplify handling of both linear and non-linear skbs, because for linear skb we need to call 'skb_pull()' after reading data from it, while in non-linear case we need to update 'data_len'. Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent b3af9c0 commit 0df7cd3

3 files changed

Lines changed: 29 additions & 18 deletions

File tree

drivers/vhost/vsock.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
114114
struct sk_buff *skb;
115115
unsigned out, in;
116116
size_t nbytes;
117+
u32 offset;
117118
int head;
118119

119120
skb = virtio_vsock_skb_dequeue(&vsock->send_pkt_queue);
@@ -156,7 +157,8 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
156157
}
157158

158159
iov_iter_init(&iov_iter, ITER_DEST, &vq->iov[out], in, iov_len);
159-
payload_len = skb->len;
160+
offset = VIRTIO_VSOCK_SKB_CB(skb)->offset;
161+
payload_len = skb->len - offset;
160162
hdr = virtio_vsock_hdr(skb);
161163

162164
/* If the packet is greater than the space available in the
@@ -197,8 +199,10 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
197199
break;
198200
}
199201

200-
nbytes = copy_to_iter(skb->data, payload_len, &iov_iter);
201-
if (nbytes != payload_len) {
202+
if (skb_copy_datagram_iter(skb,
203+
offset,
204+
&iov_iter,
205+
payload_len)) {
202206
kfree_skb(skb);
203207
vq_err(vq, "Faulted on copying pkt buf\n");
204208
break;
@@ -212,13 +216,13 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
212216
vhost_add_used(vq, head, sizeof(*hdr) + payload_len);
213217
added = true;
214218

215-
skb_pull(skb, payload_len);
219+
VIRTIO_VSOCK_SKB_CB(skb)->offset += payload_len;
216220
total_len += payload_len;
217221

218222
/* If we didn't send all the payload we can requeue the packet
219223
* to send it with the next available buffer.
220224
*/
221-
if (skb->len > 0) {
225+
if (VIRTIO_VSOCK_SKB_CB(skb)->offset < skb->len) {
222226
hdr->flags |= cpu_to_le32(flags_to_restore);
223227

224228
/* We are queueing the same skb to handle

include/linux/virtio_vsock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
struct virtio_vsock_skb_cb {
1313
bool reply;
1414
bool tap_delivered;
15+
u32 offset;
1516
};
1617

1718
#define VIRTIO_VSOCK_SKB_CB(skb) ((struct virtio_vsock_skb_cb *)((skb)->cb))

net/vmw_vsock/virtio_transport_common.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,10 @@ virtio_transport_stream_do_peek(struct vsock_sock *vsk,
364364
spin_unlock_bh(&vvs->rx_lock);
365365

366366
/* sk_lock is held by caller so no one else can dequeue.
367-
* Unlock rx_lock since memcpy_to_msg() may sleep.
367+
* Unlock rx_lock since skb_copy_datagram_iter() may sleep.
368368
*/
369-
err = memcpy_to_msg(msg, skb->data, bytes);
369+
err = skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
370+
&msg->msg_iter, bytes);
370371
if (err)
371372
goto out;
372373

@@ -410,25 +411,27 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
410411
while (total < len && !skb_queue_empty(&vvs->rx_queue)) {
411412
skb = skb_peek(&vvs->rx_queue);
412413

413-
bytes = len - total;
414-
if (bytes > skb->len)
415-
bytes = skb->len;
414+
bytes = min_t(size_t, len - total,
415+
skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset);
416416

417417
/* sk_lock is held by caller so no one else can dequeue.
418-
* Unlock rx_lock since memcpy_to_msg() may sleep.
418+
* Unlock rx_lock since skb_copy_datagram_iter() may sleep.
419419
*/
420420
spin_unlock_bh(&vvs->rx_lock);
421421

422-
err = memcpy_to_msg(msg, skb->data, bytes);
422+
err = skb_copy_datagram_iter(skb,
423+
VIRTIO_VSOCK_SKB_CB(skb)->offset,
424+
&msg->msg_iter, bytes);
423425
if (err)
424426
goto out;
425427

426428
spin_lock_bh(&vvs->rx_lock);
427429

428430
total += bytes;
429-
skb_pull(skb, bytes);
430431

431-
if (skb->len == 0) {
432+
VIRTIO_VSOCK_SKB_CB(skb)->offset += bytes;
433+
434+
if (skb->len == VIRTIO_VSOCK_SKB_CB(skb)->offset) {
432435
u32 pkt_len = le32_to_cpu(virtio_vsock_hdr(skb)->len);
433436

434437
virtio_transport_dec_rx_pkt(vvs, pkt_len);
@@ -492,9 +495,10 @@ virtio_transport_seqpacket_do_peek(struct vsock_sock *vsk,
492495
spin_unlock_bh(&vvs->rx_lock);
493496

494497
/* sk_lock is held by caller so no one else can dequeue.
495-
* Unlock rx_lock since memcpy_to_msg() may sleep.
498+
* Unlock rx_lock since skb_copy_datagram_iter() may sleep.
496499
*/
497-
err = memcpy_to_msg(msg, skb->data, bytes);
500+
err = skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
501+
&msg->msg_iter, bytes);
498502
if (err)
499503
return err;
500504

@@ -553,11 +557,13 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
553557
int err;
554558

555559
/* sk_lock is held by caller so no one else can dequeue.
556-
* Unlock rx_lock since memcpy_to_msg() may sleep.
560+
* Unlock rx_lock since skb_copy_datagram_iter() may sleep.
557561
*/
558562
spin_unlock_bh(&vvs->rx_lock);
559563

560-
err = memcpy_to_msg(msg, skb->data, bytes_to_copy);
564+
err = skb_copy_datagram_iter(skb, 0,
565+
&msg->msg_iter,
566+
bytes_to_copy);
561567
if (err) {
562568
/* Copy of message failed. Rest of
563569
* fragments will be freed without copy.

0 commit comments

Comments
 (0)