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/macvtap.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/macvtap.c')
-rw-r--r-- | drivers/net/macvtap.c | 44 |
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 */ |
642 | static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | 642 | static 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 | ||
767 | static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv, | 767 | static 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 | ||
1102 | static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, | 1100 | static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, |