diff options
author | Jason Wang <jasowang@redhat.com> | 2013-08-06 05:45:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-07 19:52:38 -0400 |
commit | 3d9953a2ef2182d56e268742259b11dedb8e281d (patch) | |
tree | a20e91bcc6cd02c8aaa6194e4be24bde9db7fb80 /net/core | |
parent | 0433547aa7443cefc89d9b533169bdc50f1206b8 (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.c | 37 |
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) |