aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvtap.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-06-19 15:36:49 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-11-24 05:15:41 -0500
commitf5ff53b4d97c62e63ee2868fd4b8d7896643ee03 (patch)
tree91c7673caa5e8898c90ff24b3509c40807843917 /drivers/net/macvtap.c
parent3a654f975bf99165016fe257a3d2b4e6716e4931 (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/macvtap.c')
-rw-r--r--drivers/net/macvtap.c44
1 files changed, 21 insertions, 23 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 8f8004552d8e..22b4cf2fa108 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -640,12 +640,12 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
640 640
641/* Get packet from user space buffer */ 641/* Get packet from user space buffer */
642static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, 642static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
643 const struct iovec *iv, unsigned long total_len, 643 struct iov_iter *from, int noblock)
644 size_t count, int noblock)
645{ 644{
646 int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); 645 int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN);
647 struct sk_buff *skb; 646 struct sk_buff *skb;
648 struct macvlan_dev *vlan; 647 struct macvlan_dev *vlan;
648 unsigned long total_len = iov_iter_count(from);
649 unsigned long len = total_len; 649 unsigned long len = total_len;
650 int err; 650 int err;
651 struct virtio_net_hdr vnet_hdr = { 0 }; 651 struct virtio_net_hdr vnet_hdr = { 0 };
@@ -653,6 +653,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
653 int copylen = 0; 653 int copylen = 0;
654 bool zerocopy = false; 654 bool zerocopy = false;
655 size_t linear; 655 size_t linear;
656 ssize_t n;
656 657
657 if (q->flags & IFF_VNET_HDR) { 658 if (q->flags & IFF_VNET_HDR) {
658 vnet_hdr_len = q->vnet_hdr_sz; 659 vnet_hdr_len = q->vnet_hdr_sz;
@@ -662,10 +663,11 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
662 goto err; 663 goto err;
663 len -= vnet_hdr_len; 664 len -= vnet_hdr_len;
664 665
665 err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, 666 err = -EFAULT;
666 sizeof(vnet_hdr)); 667 n = copy_from_iter(&vnet_hdr, sizeof(vnet_hdr), from);
667 if (err < 0) 668 if (n != sizeof(vnet_hdr))
668 goto err; 669 goto err;
670 iov_iter_advance(from, vnet_hdr_len - sizeof(vnet_hdr));
669 if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && 671 if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
670 vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 > 672 vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 >
671 vnet_hdr.hdr_len) 673 vnet_hdr.hdr_len)
@@ -680,17 +682,16 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
680 if (unlikely(len < ETH_HLEN)) 682 if (unlikely(len < ETH_HLEN))
681 goto err; 683 goto err;
682 684
683 err = -EMSGSIZE;
684 if (unlikely(count > UIO_MAXIOV))
685 goto err;
686
687 if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) { 685 if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) {
686 struct iov_iter i;
687
688 copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN; 688 copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN;
689 if (copylen > good_linear) 689 if (copylen > good_linear)
690 copylen = good_linear; 690 copylen = good_linear;
691 linear = copylen; 691 linear = copylen;
692 if (iov_pages(iv, vnet_hdr_len + copylen, count) 692 i = *from;
693 <= MAX_SKB_FRAGS) 693 iov_iter_advance(&i, copylen);
694 if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS)
694 zerocopy = true; 695 zerocopy = true;
695 } 696 }
696 697
@@ -708,10 +709,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
708 goto err; 709 goto err;
709 710
710 if (zerocopy) 711 if (zerocopy)
711 err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count); 712 err = zerocopy_sg_from_iter(skb, from);
712 else { 713 else {
713 err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, 714 err = skb_copy_datagram_from_iter(skb, 0, from, len);
714 len);
715 if (!err && m && m->msg_control) { 715 if (!err && m && m->msg_control) {
716 struct ubuf_info *uarg = m->msg_control; 716 struct ubuf_info *uarg = m->msg_control;
717 uarg->callback(uarg, false); 717 uarg->callback(uarg, false);
@@ -764,16 +764,12 @@ err:
764 return err; 764 return err;
765} 765}
766 766
767static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv, 767static ssize_t macvtap_write_iter(struct kiocb *iocb, struct iov_iter *from)
768 unsigned long count, loff_t pos)
769{ 768{
770 struct file *file = iocb->ki_filp; 769 struct file *file = iocb->ki_filp;
771 ssize_t result = -ENOLINK;
772 struct macvtap_queue *q = file->private_data; 770 struct macvtap_queue *q = file->private_data;
773 771
774 result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count, 772 return macvtap_get_user(q, NULL, from, file->f_flags & O_NONBLOCK);
775 file->f_flags & O_NONBLOCK);
776 return result;
777} 773}
778 774
779/* Put packet to the user space buffer */ 775/* Put packet to the user space buffer */
@@ -1081,8 +1077,9 @@ static const struct file_operations macvtap_fops = {
1081 .open = macvtap_open, 1077 .open = macvtap_open,
1082 .release = macvtap_release, 1078 .release = macvtap_release,
1083 .read = new_sync_read, 1079 .read = new_sync_read,
1080 .write = new_sync_write,
1084 .read_iter = macvtap_read_iter, 1081 .read_iter = macvtap_read_iter,
1085 .aio_write = macvtap_aio_write, 1082 .write_iter = macvtap_write_iter,
1086 .poll = macvtap_poll, 1083 .poll = macvtap_poll,
1087 .llseek = no_llseek, 1084 .llseek = no_llseek,
1088 .unlocked_ioctl = macvtap_ioctl, 1085 .unlocked_ioctl = macvtap_ioctl,
@@ -1095,8 +1092,9 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
1095 struct msghdr *m, size_t total_len) 1092 struct msghdr *m, size_t total_len)
1096{ 1093{
1097 struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); 1094 struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
1098 return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen, 1095 struct iov_iter from;
1099 m->msg_flags & MSG_DONTWAIT); 1096 iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len);
1097 return macvtap_get_user(q, m, &from, m->msg_flags & MSG_DONTWAIT);
1100} 1098}
1101 1099
1102static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, 1100static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,