diff options
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r-- | drivers/net/macvtap.c | 25 |
1 files changed, 9 insertions, 16 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index dc76670c2f2a..2a89da080317 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -744,7 +744,7 @@ err: | |||
744 | rcu_read_lock(); | 744 | rcu_read_lock(); |
745 | vlan = rcu_dereference(q->vlan); | 745 | vlan = rcu_dereference(q->vlan); |
746 | if (vlan) | 746 | if (vlan) |
747 | vlan->dev->stats.tx_dropped++; | 747 | this_cpu_inc(vlan->pcpu_stats->tx_dropped); |
748 | rcu_read_unlock(); | 748 | rcu_read_unlock(); |
749 | 749 | ||
750 | return err; | 750 | return err; |
@@ -767,11 +767,10 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, | |||
767 | const struct sk_buff *skb, | 767 | const struct sk_buff *skb, |
768 | const struct iovec *iv, int len) | 768 | const struct iovec *iv, int len) |
769 | { | 769 | { |
770 | struct macvlan_dev *vlan; | ||
771 | int ret; | 770 | int ret; |
772 | int vnet_hdr_len = 0; | 771 | int vnet_hdr_len = 0; |
773 | int vlan_offset = 0; | 772 | int vlan_offset = 0; |
774 | int copied; | 773 | int copied, total; |
775 | 774 | ||
776 | if (q->flags & IFF_VNET_HDR) { | 775 | if (q->flags & IFF_VNET_HDR) { |
777 | struct virtio_net_hdr vnet_hdr; | 776 | struct virtio_net_hdr vnet_hdr; |
@@ -786,7 +785,8 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, | |||
786 | if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) | 785 | if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) |
787 | return -EFAULT; | 786 | return -EFAULT; |
788 | } | 787 | } |
789 | copied = vnet_hdr_len; | 788 | total = copied = vnet_hdr_len; |
789 | total += skb->len; | ||
790 | 790 | ||
791 | if (!vlan_tx_tag_present(skb)) | 791 | if (!vlan_tx_tag_present(skb)) |
792 | len = min_t(int, skb->len, len); | 792 | len = min_t(int, skb->len, len); |
@@ -801,6 +801,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, | |||
801 | 801 | ||
802 | vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); | 802 | vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); |
803 | len = min_t(int, skb->len + VLAN_HLEN, len); | 803 | len = min_t(int, skb->len + VLAN_HLEN, len); |
804 | total += VLAN_HLEN; | ||
804 | 805 | ||
805 | copy = min_t(int, vlan_offset, len); | 806 | copy = min_t(int, vlan_offset, len); |
806 | ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); | 807 | ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); |
@@ -818,19 +819,9 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, | |||
818 | } | 819 | } |
819 | 820 | ||
820 | ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); | 821 | ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); |
821 | copied += len; | ||
822 | 822 | ||
823 | done: | 823 | done: |
824 | rcu_read_lock(); | 824 | return ret ? ret : total; |
825 | vlan = rcu_dereference(q->vlan); | ||
826 | if (vlan) { | ||
827 | preempt_disable(); | ||
828 | macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0); | ||
829 | preempt_enable(); | ||
830 | } | ||
831 | rcu_read_unlock(); | ||
832 | |||
833 | return ret ? ret : copied; | ||
834 | } | 825 | } |
835 | 826 | ||
836 | static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, | 827 | static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, |
@@ -885,7 +876,9 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, | |||
885 | } | 876 | } |
886 | 877 | ||
887 | ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK); | 878 | ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK); |
888 | ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */ | 879 | ret = min_t(ssize_t, ret, len); |
880 | if (ret > 0) | ||
881 | iocb->ki_pos = ret; | ||
889 | out: | 882 | out: |
890 | return ret; | 883 | return ret; |
891 | } | 884 | } |