diff options
| -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) |
