aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vhost
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-12-10 15:51:28 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-02-04 01:34:16 -0500
commitba7438aed924133df54a60e4cd5499d359bcf2a8 (patch)
treee29c9a26421611c374667b022c9904ab527c496f /drivers/vhost
parent98a527aac1eb198dbc4405b800e102563ed8e4dd (diff)
vhost: don't bother copying iovecs in handle_rx(), kill memcpy_toiovecend()
Cc: Michael S. Tsirkin <mst@redhat.com> Cc: kvm@vger.kernel.org Cc: virtualization@lists.linux-foundation.org Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers/vhost')
-rw-r--r--drivers/vhost/net.c82
1 files changed, 23 insertions, 59 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index d86cc9bb9ea4..e022cc40303d 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -84,10 +84,6 @@ struct vhost_net_ubuf_ref {
84 84
85struct vhost_net_virtqueue { 85struct vhost_net_virtqueue {
86 struct vhost_virtqueue vq; 86 struct vhost_virtqueue vq;
87 /* hdr is used to store the virtio header.
88 * Since each iovec has >= 1 byte length, we never need more than
89 * header length entries to store the header. */
90 struct iovec hdr[sizeof(struct virtio_net_hdr_mrg_rxbuf)];
91 size_t vhost_hlen; 87 size_t vhost_hlen;
92 size_t sock_hlen; 88 size_t sock_hlen;
93 /* vhost zerocopy support fields below: */ 89 /* vhost zerocopy support fields below: */
@@ -235,44 +231,6 @@ static bool vhost_sock_zcopy(struct socket *sock)
235 sock_flag(sock->sk, SOCK_ZEROCOPY); 231 sock_flag(sock->sk, SOCK_ZEROCOPY);
236} 232}
237 233
238/* Pop first len bytes from iovec. Return number of segments used. */
239static int move_iovec_hdr(struct iovec *from, struct iovec *to,
240 size_t len, int iov_count)
241{
242 int seg = 0;
243 size_t size;
244
245 while (len && seg < iov_count) {
246 size = min(from->iov_len, len);
247 to->iov_base = from->iov_base;
248 to->iov_len = size;
249 from->iov_len -= size;
250 from->iov_base += size;
251 len -= size;
252 ++from;
253 ++to;
254 ++seg;
255 }
256 return seg;
257}
258/* Copy iovec entries for len bytes from iovec. */
259static void copy_iovec_hdr(const struct iovec *from, struct iovec *to,
260 size_t len, int iovcount)
261{
262 int seg = 0;
263 size_t size;
264
265 while (len && seg < iovcount) {
266 size = min(from->iov_len, len);
267 to->iov_base = from->iov_base;
268 to->iov_len = size;
269 len -= size;
270 ++from;
271 ++to;
272 ++seg;
273 }
274}
275
276/* In case of DMA done not in order in lower device driver for some reason. 234/* In case of DMA done not in order in lower device driver for some reason.
277 * upend_idx is used to track end of used idx, done_idx is used to track head 235 * upend_idx is used to track end of used idx, done_idx is used to track head
278 * of used idx. Once lower device DMA done contiguously, we will signal KVM 236 * of used idx. Once lower device DMA done contiguously, we will signal KVM
@@ -570,9 +528,9 @@ static void handle_rx(struct vhost_net *net)
570 .msg_controllen = 0, 528 .msg_controllen = 0,
571 .msg_flags = MSG_DONTWAIT, 529 .msg_flags = MSG_DONTWAIT,
572 }; 530 };
573 struct virtio_net_hdr_mrg_rxbuf hdr = { 531 struct virtio_net_hdr hdr = {
574 .hdr.flags = 0, 532 .flags = 0,
575 .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE 533 .gso_type = VIRTIO_NET_HDR_GSO_NONE
576 }; 534 };
577 size_t total_len = 0; 535 size_t total_len = 0;
578 int err, mergeable; 536 int err, mergeable;
@@ -580,6 +538,7 @@ static void handle_rx(struct vhost_net *net)
580 size_t vhost_hlen, sock_hlen; 538 size_t vhost_hlen, sock_hlen;
581 size_t vhost_len, sock_len; 539 size_t vhost_len, sock_len;
582 struct socket *sock; 540 struct socket *sock;
541 struct iov_iter fixup;
583 542
584 mutex_lock(&vq->mutex); 543 mutex_lock(&vq->mutex);
585 sock = vq->private_data; 544 sock = vq->private_data;
@@ -624,14 +583,19 @@ static void handle_rx(struct vhost_net *net)
624 break; 583 break;
625 } 584 }
626 /* We don't need to be notified again. */ 585 /* We don't need to be notified again. */
627 if (unlikely((vhost_hlen))) 586 iov_iter_init(&msg.msg_iter, READ, vq->iov, in, vhost_len);
628 /* Skip header. TODO: support TSO. */ 587 fixup = msg.msg_iter;
629 move_iovec_hdr(vq->iov, nvq->hdr, vhost_hlen, in); 588 if (unlikely((vhost_hlen))) {
630 else 589 /* We will supply the header ourselves
631 /* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF: 590 * TODO: support TSO.
632 * needed because recvmsg can modify msg_iov. */ 591 */
633 copy_iovec_hdr(vq->iov, nvq->hdr, sock_hlen, in); 592 iov_iter_advance(&msg.msg_iter, vhost_hlen);
634 iov_iter_init(&msg.msg_iter, READ, vq->iov, in, sock_len); 593 } else {
594 /* It'll come from socket; we'll need to patch
595 * ->num_buffers over if VIRTIO_NET_F_MRG_RXBUF
596 */
597 iov_iter_advance(&fixup, sizeof(hdr));
598 }
635 err = sock->ops->recvmsg(NULL, sock, &msg, 599 err = sock->ops->recvmsg(NULL, sock, &msg,
636 sock_len, MSG_DONTWAIT | MSG_TRUNC); 600 sock_len, MSG_DONTWAIT | MSG_TRUNC);
637 /* Userspace might have consumed the packet meanwhile: 601 /* Userspace might have consumed the packet meanwhile:
@@ -643,18 +607,18 @@ static void handle_rx(struct vhost_net *net)
643 vhost_discard_vq_desc(vq, headcount); 607 vhost_discard_vq_desc(vq, headcount);
644 continue; 608 continue;
645 } 609 }
610 /* Supply virtio_net_hdr if VHOST_NET_F_VIRTIO_NET_HDR */
646 if (unlikely(vhost_hlen) && 611 if (unlikely(vhost_hlen) &&
647 memcpy_toiovecend(nvq->hdr, (unsigned char *)&hdr, 0, 612 copy_to_iter(&hdr, sizeof(hdr), &fixup) != sizeof(hdr)) {
648 vhost_hlen)) {
649 vq_err(vq, "Unable to write vnet_hdr at addr %p\n", 613 vq_err(vq, "Unable to write vnet_hdr at addr %p\n",
650 vq->iov->iov_base); 614 vq->iov->iov_base);
651 break; 615 break;
652 } 616 }
653 /* TODO: Should check and handle checksum. */ 617 /* Supply (or replace) ->num_buffers if VIRTIO_NET_F_MRG_RXBUF
618 * TODO: Should check and handle checksum.
619 */
654 if (likely(mergeable) && 620 if (likely(mergeable) &&
655 memcpy_toiovecend(nvq->hdr, (unsigned char *)&headcount, 621 copy_to_iter(&headcount, 2, &fixup) != 2) {
656 offsetof(typeof(hdr), num_buffers),
657 sizeof hdr.num_buffers)) {
658 vq_err(vq, "Failed num_buffers write"); 622 vq_err(vq, "Failed num_buffers write");
659 vhost_discard_vq_desc(vq, headcount); 623 vhost_discard_vq_desc(vq, headcount);
660 break; 624 break;