macvtap: Do not double-count received packets
[deliverable/linux.git] / drivers / net / macvtap.c
index 9dccb1edfd2aba2070023f4ae874bac0cc432293..9093004f9b63004922a0202180d7341343287553 100644 (file)
@@ -628,6 +628,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
                                const struct iovec *iv, unsigned long total_len,
                                size_t count, int noblock)
 {
+       int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN);
        struct sk_buff *skb;
        struct macvlan_dev *vlan;
        unsigned long len = total_len;
@@ -670,6 +671,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
 
        if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) {
                copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN;
+               if (copylen > good_linear)
+                       copylen = good_linear;
                linear = copylen;
                if (iov_pages(iv, vnet_hdr_len + copylen, count)
                    <= MAX_SKB_FRAGS)
@@ -678,7 +681,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
 
        if (!zerocopy) {
                copylen = len;
-               linear = vnet_hdr.hdr_len;
+               if (vnet_hdr.hdr_len > good_linear)
+                       linear = good_linear;
+               else
+                       linear = vnet_hdr.hdr_len;
        }
 
        skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
@@ -738,7 +744,7 @@ err:
        rcu_read_lock();
        vlan = rcu_dereference(q->vlan);
        if (vlan)
-               vlan->dev->stats.tx_dropped++;
+               this_cpu_inc(vlan->pcpu_stats->tx_dropped);
        rcu_read_unlock();
 
        return err;
@@ -761,7 +767,6 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                                const struct sk_buff *skb,
                                const struct iovec *iv, int len)
 {
-       struct macvlan_dev *vlan;
        int ret;
        int vnet_hdr_len = 0;
        int vlan_offset = 0;
@@ -815,15 +820,6 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
        copied += len;
 
 done:
-       rcu_read_lock();
-       vlan = rcu_dereference(q->vlan);
-       if (vlan) {
-               preempt_disable();
-               macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0);
-               preempt_enable();
-       }
-       rcu_read_unlock();
-
        return ret ? ret : copied;
 }
 
This page took 0.026458 seconds and 5 git commands to generate.