diff options
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 80 |
1 files changed, 0 insertions, 80 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 18527ef0cc75..b1630479d4a1 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -961,86 +961,6 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, | |||
961 | return skb; | 961 | return skb; |
962 | } | 962 | } |
963 | 963 | ||
964 | /* set skb frags from iovec, this can move to core network code for reuse */ | ||
965 | static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, | ||
966 | int offset, size_t count) | ||
967 | { | ||
968 | int len = iov_length(from, count) - offset; | ||
969 | int copy = skb_headlen(skb); | ||
970 | int size, offset1 = 0; | ||
971 | int i = 0; | ||
972 | |||
973 | /* Skip over from offset */ | ||
974 | while (count && (offset >= from->iov_len)) { | ||
975 | offset -= from->iov_len; | ||
976 | ++from; | ||
977 | --count; | ||
978 | } | ||
979 | |||
980 | /* copy up to skb headlen */ | ||
981 | while (count && (copy > 0)) { | ||
982 | size = min_t(unsigned int, copy, from->iov_len - offset); | ||
983 | if (copy_from_user(skb->data + offset1, from->iov_base + offset, | ||
984 | size)) | ||
985 | return -EFAULT; | ||
986 | if (copy > size) { | ||
987 | ++from; | ||
988 | --count; | ||
989 | offset = 0; | ||
990 | } else | ||
991 | offset += size; | ||
992 | copy -= size; | ||
993 | offset1 += size; | ||
994 | } | ||
995 | |||
996 | if (len == offset1) | ||
997 | return 0; | ||
998 | |||
999 | while (count--) { | ||
1000 | struct page *page[MAX_SKB_FRAGS]; | ||
1001 | int num_pages; | ||
1002 | unsigned long base; | ||
1003 | unsigned long truesize; | ||
1004 | |||
1005 | len = from->iov_len - offset; | ||
1006 | if (!len) { | ||
1007 | offset = 0; | ||
1008 | ++from; | ||
1009 | continue; | ||
1010 | } | ||
1011 | base = (unsigned long)from->iov_base + offset; | ||
1012 | size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; | ||
1013 | if (i + size > MAX_SKB_FRAGS) | ||
1014 | return -EMSGSIZE; | ||
1015 | num_pages = get_user_pages_fast(base, size, 0, &page[i]); | ||
1016 | if (num_pages != size) { | ||
1017 | int j; | ||
1018 | |||
1019 | for (j = 0; j < num_pages; j++) | ||
1020 | put_page(page[i + j]); | ||
1021 | return -EFAULT; | ||
1022 | } | ||
1023 | truesize = size * PAGE_SIZE; | ||
1024 | skb->data_len += len; | ||
1025 | skb->len += len; | ||
1026 | skb->truesize += truesize; | ||
1027 | atomic_add(truesize, &skb->sk->sk_wmem_alloc); | ||
1028 | while (len) { | ||
1029 | int off = base & ~PAGE_MASK; | ||
1030 | int size = min_t(int, len, PAGE_SIZE - off); | ||
1031 | __skb_fill_page_desc(skb, i, page[i], off, size); | ||
1032 | skb_shinfo(skb)->nr_frags++; | ||
1033 | /* increase sk_wmem_alloc */ | ||
1034 | base += size; | ||
1035 | len -= size; | ||
1036 | i++; | ||
1037 | } | ||
1038 | offset = 0; | ||
1039 | ++from; | ||
1040 | } | ||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | /* Get packet from user space buffer */ | 964 | /* Get packet from user space buffer */ |
1045 | static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | 965 | static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, |
1046 | void *msg_control, const struct iovec *iv, | 966 | void *msg_control, const struct iovec *iv, |