aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-08-06 05:45:08 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-07 19:52:38 -0400
commit3d9953a2ef2182d56e268742259b11dedb8e281d (patch)
treea20e91bcc6cd02c8aaa6194e4be24bde9db7fb80 /net/core
parent0433547aa7443cefc89d9b533169bdc50f1206b8 (diff)
net: use skb_copy_datagram_from_iovec() in zerocopy_sg_from_iovec()
Use skb_copy_datagram_from_iovec() to avoid code duplication and make it easy to be read. Also we can do the skipping inside the zero-copy loop. Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/datagram.c37
1 files changed, 10 insertions, 27 deletions
diff --git a/net/core/datagram.c b/net/core/datagram.c
index badcd93e5dd8..af814e764206 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -591,48 +591,31 @@ int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
591 int offset, size_t count) 591 int offset, size_t count)
592{ 592{
593 int len = iov_length(from, count) - offset; 593 int len = iov_length(from, count) - offset;
594 int copy = skb_headlen(skb); 594 int copy = min_t(int, skb_headlen(skb), len);
595 int size, offset1 = 0; 595 int size;
596 int i = 0; 596 int i = 0;
597 597
598 /* Skip over from offset */
599 while (count && (offset >= from->iov_len)) {
600 offset -= from->iov_len;
601 ++from;
602 --count;
603 }
604
605 /* copy up to skb headlen */ 598 /* copy up to skb headlen */
606 while (count && (copy > 0)) { 599 if (skb_copy_datagram_from_iovec(skb, 0, from, offset, copy))
607 size = min_t(unsigned int, copy, from->iov_len - offset); 600 return -EFAULT;
608 if (copy_from_user(skb->data + offset1, from->iov_base + offset,
609 size))
610 return -EFAULT;
611 if (copy > size) {
612 ++from;
613 --count;
614 offset = 0;
615 } else
616 offset += size;
617 copy -= size;
618 offset1 += size;
619 }
620 601
621 if (len == offset1) 602 if (len == copy)
622 return 0; 603 return 0;
623 604
605 offset += copy;
624 while (count--) { 606 while (count--) {
625 struct page *page[MAX_SKB_FRAGS]; 607 struct page *page[MAX_SKB_FRAGS];
626 int num_pages; 608 int num_pages;
627 unsigned long base; 609 unsigned long base;
628 unsigned long truesize; 610 unsigned long truesize;
629 611
630 len = from->iov_len - offset; 612 /* Skip over from offset and copied */
631 if (!len) { 613 if (offset >= from->iov_len) {
632 offset = 0; 614 offset -= from->iov_len;
633 ++from; 615 ++from;
634 continue; 616 continue;
635 } 617 }
618 len = from->iov_len - offset;
636 base = (unsigned long)from->iov_base + offset; 619 base = (unsigned long)from->iov_base + offset;
637 size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; 620 size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
638 if (i + size > MAX_SKB_FRAGS) 621 if (i + size > MAX_SKB_FRAGS)