summaryrefslogtreecommitdiffstats
path: root/drivers/net/macvtap.c
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-08-06 05:45:04 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-07 19:52:34 -0400
commitc3bdeb5c7cc073ccf5ff9624642022a8613a956e (patch)
tree59dd31538e9da9d5adecbc9c96d7d8a1aa0aa50d /drivers/net/macvtap.c
parentb4bf07771faaf959b0a916d35b1b930c030e30a8 (diff)
net: move zerocopy_sg_from_iovec() to net/core/datagram.c
To let it be reused and reduce code duplication. Also document this function. Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r--drivers/net/macvtap.c80
1 files changed, 0 insertions, 80 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index dfec20df17ba..182364abfa35 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -536,86 +536,6 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad,
536 return skb; 536 return skb;
537} 537}
538 538
539/* set skb frags from iovec, this can move to core network code for reuse */
540static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
541 int offset, size_t count)
542{
543 int len = iov_length(from, count) - offset;
544 int copy = skb_headlen(skb);
545 int size, offset1 = 0;
546 int i = 0;
547
548 /* Skip over from offset */
549 while (count && (offset >= from->iov_len)) {
550 offset -= from->iov_len;
551 ++from;
552 --count;
553 }
554
555 /* copy up to skb headlen */
556 while (count && (copy > 0)) {
557 size = min_t(unsigned int, copy, from->iov_len - offset);
558 if (copy_from_user(skb->data + offset1, from->iov_base + offset,
559 size))
560 return -EFAULT;
561 if (copy > size) {
562 ++from;
563 --count;
564 offset = 0;
565 } else
566 offset += size;
567 copy -= size;
568 offset1 += size;
569 }
570
571 if (len == offset1)
572 return 0;
573
574 while (count--) {
575 struct page *page[MAX_SKB_FRAGS];
576 int num_pages;
577 unsigned long base;
578 unsigned long truesize;
579
580 len = from->iov_len - offset;
581 if (!len) {
582 offset = 0;
583 ++from;
584 continue;
585 }
586 base = (unsigned long)from->iov_base + offset;
587 size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
588 if (i + size > MAX_SKB_FRAGS)
589 return -EMSGSIZE;
590 num_pages = get_user_pages_fast(base, size, 0, &page[i]);
591 if (num_pages != size) {
592 int j;
593
594 for (j = 0; j < num_pages; j++)
595 put_page(page[i + j]);
596 return -EFAULT;
597 }
598 truesize = size * PAGE_SIZE;
599 skb->data_len += len;
600 skb->len += len;
601 skb->truesize += truesize;
602 atomic_add(truesize, &skb->sk->sk_wmem_alloc);
603 while (len) {
604 int off = base & ~PAGE_MASK;
605 int size = min_t(int, len, PAGE_SIZE - off);
606 __skb_fill_page_desc(skb, i, page[i], off, size);
607 skb_shinfo(skb)->nr_frags++;
608 /* increase sk_wmem_alloc */
609 base += size;
610 len -= size;
611 i++;
612 }
613 offset = 0;
614 ++from;
615 }
616 return 0;
617}
618
619/* 539/*
620 * macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should 540 * macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should
621 * be shared with the tun/tap driver. 541 * be shared with the tun/tap driver.