diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-06-19 15:36:49 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-24 05:15:41 -0500 |
commit | f5ff53b4d97c62e63ee2868fd4b8d7896643ee03 (patch) | |
tree | 91c7673caa5e8898c90ff24b3509c40807843917 /drivers/net/tun.c | |
parent | 3a654f975bf99165016fe257a3d2b4e6716e4931 (diff) |
{macvtap,tun}_get_user(): switch to iov_iter
allows to switch macvtap and tun from ->aio_write() to ->write_iter()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 44 |
1 files changed, 24 insertions, 20 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 405dfdf4f8c8..4b743c612624 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -1012,28 +1012,29 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, | |||
1012 | 1012 | ||
1013 | /* Get packet from user space buffer */ | 1013 | /* Get packet from user space buffer */ |
1014 | static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | 1014 | static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, |
1015 | void *msg_control, const struct iovec *iv, | 1015 | void *msg_control, struct iov_iter *from, |
1016 | size_t total_len, size_t count, int noblock) | 1016 | int noblock) |
1017 | { | 1017 | { |
1018 | struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; | 1018 | struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; |
1019 | struct sk_buff *skb; | 1019 | struct sk_buff *skb; |
1020 | size_t total_len = iov_iter_count(from); | ||
1020 | size_t len = total_len, align = NET_SKB_PAD, linear; | 1021 | size_t len = total_len, align = NET_SKB_PAD, linear; |
1021 | struct virtio_net_hdr gso = { 0 }; | 1022 | struct virtio_net_hdr gso = { 0 }; |
1022 | int good_linear; | 1023 | int good_linear; |
1023 | int offset = 0; | ||
1024 | int copylen; | 1024 | int copylen; |
1025 | bool zerocopy = false; | 1025 | bool zerocopy = false; |
1026 | int err; | 1026 | int err; |
1027 | u32 rxhash; | 1027 | u32 rxhash; |
1028 | ssize_t n; | ||
1028 | 1029 | ||
1029 | if (!(tun->flags & TUN_NO_PI)) { | 1030 | if (!(tun->flags & TUN_NO_PI)) { |
1030 | if (len < sizeof(pi)) | 1031 | if (len < sizeof(pi)) |
1031 | return -EINVAL; | 1032 | return -EINVAL; |
1032 | len -= sizeof(pi); | 1033 | len -= sizeof(pi); |
1033 | 1034 | ||
1034 | if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) | 1035 | n = copy_from_iter(&pi, sizeof(pi), from); |
1036 | if (n != sizeof(pi)) | ||
1035 | return -EFAULT; | 1037 | return -EFAULT; |
1036 | offset += sizeof(pi); | ||
1037 | } | 1038 | } |
1038 | 1039 | ||
1039 | if (tun->flags & TUN_VNET_HDR) { | 1040 | if (tun->flags & TUN_VNET_HDR) { |
@@ -1041,7 +1042,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1041 | return -EINVAL; | 1042 | return -EINVAL; |
1042 | len -= tun->vnet_hdr_sz; | 1043 | len -= tun->vnet_hdr_sz; |
1043 | 1044 | ||
1044 | if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) | 1045 | n = copy_from_iter(&gso, sizeof(gso), from); |
1046 | if (n != sizeof(gso)) | ||
1045 | return -EFAULT; | 1047 | return -EFAULT; |
1046 | 1048 | ||
1047 | if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && | 1049 | if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
@@ -1050,7 +1052,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1050 | 1052 | ||
1051 | if (gso.hdr_len > len) | 1053 | if (gso.hdr_len > len) |
1052 | return -EINVAL; | 1054 | return -EINVAL; |
1053 | offset += tun->vnet_hdr_sz; | 1055 | iov_iter_advance(from, tun->vnet_hdr_sz); |
1054 | } | 1056 | } |
1055 | 1057 | ||
1056 | if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { | 1058 | if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { |
@@ -1063,6 +1065,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1063 | good_linear = SKB_MAX_HEAD(align); | 1065 | good_linear = SKB_MAX_HEAD(align); |
1064 | 1066 | ||
1065 | if (msg_control) { | 1067 | if (msg_control) { |
1068 | struct iov_iter i = *from; | ||
1069 | |||
1066 | /* There are 256 bytes to be copied in skb, so there is | 1070 | /* There are 256 bytes to be copied in skb, so there is |
1067 | * enough room for skb expand head in case it is used. | 1071 | * enough room for skb expand head in case it is used. |
1068 | * The rest of the buffer is mapped from userspace. | 1072 | * The rest of the buffer is mapped from userspace. |
@@ -1071,7 +1075,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1071 | if (copylen > good_linear) | 1075 | if (copylen > good_linear) |
1072 | copylen = good_linear; | 1076 | copylen = good_linear; |
1073 | linear = copylen; | 1077 | linear = copylen; |
1074 | if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) | 1078 | iov_iter_advance(&i, copylen); |
1079 | if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS) | ||
1075 | zerocopy = true; | 1080 | zerocopy = true; |
1076 | } | 1081 | } |
1077 | 1082 | ||
@@ -1091,9 +1096,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1091 | } | 1096 | } |
1092 | 1097 | ||
1093 | if (zerocopy) | 1098 | if (zerocopy) |
1094 | err = zerocopy_sg_from_iovec(skb, iv, offset, count); | 1099 | err = zerocopy_sg_from_iter(skb, from); |
1095 | else { | 1100 | else { |
1096 | err = skb_copy_datagram_from_iovec(skb, 0, iv, offset, len); | 1101 | err = skb_copy_datagram_from_iter(skb, 0, from, len); |
1097 | if (!err && msg_control) { | 1102 | if (!err && msg_control) { |
1098 | struct ubuf_info *uarg = msg_control; | 1103 | struct ubuf_info *uarg = msg_control; |
1099 | uarg->callback(uarg, false); | 1104 | uarg->callback(uarg, false); |
@@ -1207,8 +1212,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1207 | return total_len; | 1212 | return total_len; |
1208 | } | 1213 | } |
1209 | 1214 | ||
1210 | static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, | 1215 | static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from) |
1211 | unsigned long count, loff_t pos) | ||
1212 | { | 1216 | { |
1213 | struct file *file = iocb->ki_filp; | 1217 | struct file *file = iocb->ki_filp; |
1214 | struct tun_struct *tun = tun_get(file); | 1218 | struct tun_struct *tun = tun_get(file); |
@@ -1218,10 +1222,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, | |||
1218 | if (!tun) | 1222 | if (!tun) |
1219 | return -EBADFD; | 1223 | return -EBADFD; |
1220 | 1224 | ||
1221 | tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count); | 1225 | result = tun_get_user(tun, tfile, NULL, from, file->f_flags & O_NONBLOCK); |
1222 | |||
1223 | result = tun_get_user(tun, tfile, NULL, iv, iov_length(iv, count), | ||
1224 | count, file->f_flags & O_NONBLOCK); | ||
1225 | 1226 | ||
1226 | tun_put(tun); | 1227 | tun_put(tun); |
1227 | return result; | 1228 | return result; |
@@ -1445,11 +1446,14 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1445 | int ret; | 1446 | int ret; |
1446 | struct tun_file *tfile = container_of(sock, struct tun_file, socket); | 1447 | struct tun_file *tfile = container_of(sock, struct tun_file, socket); |
1447 | struct tun_struct *tun = __tun_get(tfile); | 1448 | struct tun_struct *tun = __tun_get(tfile); |
1449 | struct iov_iter from; | ||
1448 | 1450 | ||
1449 | if (!tun) | 1451 | if (!tun) |
1450 | return -EBADFD; | 1452 | return -EBADFD; |
1451 | ret = tun_get_user(tun, tfile, m->msg_control, m->msg_iov, total_len, | 1453 | |
1452 | m->msg_iovlen, m->msg_flags & MSG_DONTWAIT); | 1454 | iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len); |
1455 | ret = tun_get_user(tun, tfile, m->msg_control, &from, | ||
1456 | m->msg_flags & MSG_DONTWAIT); | ||
1453 | tun_put(tun); | 1457 | tun_put(tun); |
1454 | return ret; | 1458 | return ret; |
1455 | } | 1459 | } |
@@ -2233,9 +2237,9 @@ static const struct file_operations tun_fops = { | |||
2233 | .owner = THIS_MODULE, | 2237 | .owner = THIS_MODULE, |
2234 | .llseek = no_llseek, | 2238 | .llseek = no_llseek, |
2235 | .read = new_sync_read, | 2239 | .read = new_sync_read, |
2240 | .write = new_sync_write, | ||
2236 | .read_iter = tun_chr_read_iter, | 2241 | .read_iter = tun_chr_read_iter, |
2237 | .write = do_sync_write, | 2242 | .write_iter = tun_chr_write_iter, |
2238 | .aio_write = tun_chr_aio_write, | ||
2239 | .poll = tun_chr_poll, | 2243 | .poll = tun_chr_poll, |
2240 | .unlocked_ioctl = tun_chr_ioctl, | 2244 | .unlocked_ioctl = tun_chr_ioctl, |
2241 | #ifdef CONFIG_COMPAT | 2245 | #ifdef CONFIG_COMPAT |