|
@@ -591,48 +591,31 @@ int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
|
|
int offset, size_t count)
|
|
|
{
|
|
|
int len = iov_length(from, count) - offset;
|
|
|
- int copy = skb_headlen(skb);
|
|
|
- int size, offset1 = 0;
|
|
|
+ int copy = min_t(int, skb_headlen(skb), len);
|
|
|
+ int size;
|
|
|
int i = 0;
|
|
|
|
|
|
- /* Skip over from offset */
|
|
|
- while (count && (offset >= from->iov_len)) {
|
|
|
- offset -= from->iov_len;
|
|
|
- ++from;
|
|
|
- --count;
|
|
|
- }
|
|
|
-
|
|
|
/* copy up to skb headlen */
|
|
|
- while (count && (copy > 0)) {
|
|
|
- size = min_t(unsigned int, copy, from->iov_len - offset);
|
|
|
- if (copy_from_user(skb->data + offset1, from->iov_base + offset,
|
|
|
- size))
|
|
|
- return -EFAULT;
|
|
|
- if (copy > size) {
|
|
|
- ++from;
|
|
|
- --count;
|
|
|
- offset = 0;
|
|
|
- } else
|
|
|
- offset += size;
|
|
|
- copy -= size;
|
|
|
- offset1 += size;
|
|
|
- }
|
|
|
+ if (skb_copy_datagram_from_iovec(skb, 0, from, offset, copy))
|
|
|
+ return -EFAULT;
|
|
|
|
|
|
- if (len == offset1)
|
|
|
+ if (len == copy)
|
|
|
return 0;
|
|
|
|
|
|
+ offset += copy;
|
|
|
while (count--) {
|
|
|
struct page *page[MAX_SKB_FRAGS];
|
|
|
int num_pages;
|
|
|
unsigned long base;
|
|
|
unsigned long truesize;
|
|
|
|
|
|
- len = from->iov_len - offset;
|
|
|
- if (!len) {
|
|
|
- offset = 0;
|
|
|
+ /* Skip over from offset and copied */
|
|
|
+ if (offset >= from->iov_len) {
|
|
|
+ offset -= from->iov_len;
|
|
|
++from;
|
|
|
continue;
|
|
|
}
|
|
|
+ len = from->iov_len - offset;
|
|
|
base = (unsigned long)from->iov_base + offset;
|
|
|
size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
|
|
|
if (i + size > MAX_SKB_FRAGS)
|