]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/tun.c
Merge tag '5.5-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
[linux.git] / drivers / net / tun.c
index 812dc3a65efbb9d1ee2724e73978dbc4803ec171..683d371e6e82063bec7ade102a3b40aa38b1b6af 100644 (file)
@@ -136,10 +136,10 @@ struct tap_filter {
 #define TUN_FLOW_EXPIRE (3 * HZ)
 
 struct tun_pcpu_stats {
-       u64 rx_packets;
-       u64 rx_bytes;
-       u64 tx_packets;
-       u64 tx_bytes;
+       u64_stats_t rx_packets;
+       u64_stats_t rx_bytes;
+       u64_stats_t tx_packets;
+       u64_stats_t tx_bytes;
        struct u64_stats_sync syncp;
        u32 rx_dropped;
        u32 tx_dropped;
@@ -313,8 +313,8 @@ static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile,
        tfile->napi_enabled = napi_en;
        tfile->napi_frags_enabled = napi_en && napi_frags;
        if (napi_en) {
-               netif_napi_add(tun->dev, &tfile->napi, tun_napi_poll,
-                              NAPI_POLL_WEIGHT);
+               netif_tx_napi_add(tun->dev, &tfile->napi, tun_napi_poll,
+                                 NAPI_POLL_WEIGHT);
                napi_enable(&tfile->napi);
        }
 }
@@ -526,8 +526,8 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
        e = tun_flow_find(head, rxhash);
        if (likely(e)) {
                /* TODO: keep queueing to old queue until it's empty? */
-               if (e->queue_index != queue_index)
-                       e->queue_index = queue_index;
+               if (READ_ONCE(e->queue_index) != queue_index)
+                       WRITE_ONCE(e->queue_index, queue_index);
                if (e->updated != jiffies)
                        e->updated = jiffies;
                sock_rps_record_flow_hash(e->rps_rxhash);
@@ -1167,10 +1167,10 @@ tun_net_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
                p = per_cpu_ptr(tun->pcpu_stats, i);
                do {
                        start = u64_stats_fetch_begin(&p->syncp);
-                       rxpackets       = p->rx_packets;
-                       rxbytes         = p->rx_bytes;
-                       txpackets       = p->tx_packets;
-                       txbytes         = p->tx_bytes;
+                       rxpackets       = u64_stats_read(&p->rx_packets);
+                       rxbytes         = u64_stats_read(&p->rx_bytes);
+                       txpackets       = u64_stats_read(&p->tx_packets);
+                       txbytes         = u64_stats_read(&p->tx_bytes);
                } while (u64_stats_fetch_retry(&p->syncp, start));
 
                stats->rx_packets       += rxpackets;
@@ -1998,8 +1998,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 
        stats = get_cpu_ptr(tun->pcpu_stats);
        u64_stats_update_begin(&stats->syncp);
-       stats->rx_packets++;
-       stats->rx_bytes += len;
+       u64_stats_inc(&stats->rx_packets);
+       u64_stats_add(&stats->rx_bytes, len);
        u64_stats_update_end(&stats->syncp);
        put_cpu_ptr(stats);
 
@@ -2052,8 +2052,8 @@ static ssize_t tun_put_user_xdp(struct tun_struct *tun,
 
        stats = get_cpu_ptr(tun->pcpu_stats);
        u64_stats_update_begin(&stats->syncp);
-       stats->tx_packets++;
-       stats->tx_bytes += ret;
+       u64_stats_inc(&stats->tx_packets);
+       u64_stats_add(&stats->tx_bytes, ret);
        u64_stats_update_end(&stats->syncp);
        put_cpu_ptr(tun->pcpu_stats);
 
@@ -2147,8 +2147,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
        /* caller is in process context, */
        stats = get_cpu_ptr(tun->pcpu_stats);
        u64_stats_update_begin(&stats->syncp);
-       stats->tx_packets++;
-       stats->tx_bytes += skb->len + vlan_hlen;
+       u64_stats_inc(&stats->tx_packets);
+       u64_stats_add(&stats->tx_bytes, skb->len + vlan_hlen);
        u64_stats_update_end(&stats->syncp);
        put_cpu_ptr(tun->pcpu_stats);
 
@@ -2290,7 +2290,13 @@ static void tun_free_netdev(struct net_device *dev)
        struct tun_struct *tun = netdev_priv(dev);
 
        BUG_ON(!(list_empty(&tun->disabled)));
+
        free_percpu(tun->pcpu_stats);
+       /* We clear pcpu_stats so that tun_set_iff() can tell if
+        * tun_free_netdev() has been called from register_netdevice().
+        */
+       tun->pcpu_stats = NULL;
+
        tun_flow_uninit(tun);
        security_tun_dev_free_security(tun->security);
        __tun_set_ebpf(tun, &tun->steering_prog, NULL);
@@ -2505,8 +2511,8 @@ static int tun_xdp_one(struct tun_struct *tun,
         */
        stats = this_cpu_ptr(tun->pcpu_stats);
        u64_stats_update_begin(&stats->syncp);
-       stats->rx_packets++;
-       stats->rx_bytes += datasize;
+       u64_stats_inc(&stats->rx_packets);
+       u64_stats_add(&stats->rx_bytes, datasize);
        u64_stats_update_end(&stats->syncp);
 
        if (rxhash)
@@ -2782,9 +2788,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
                if (!dev)
                        return -ENOMEM;
-               err = dev_get_valid_name(net, dev, name);
-               if (err < 0)
-                       goto err_free_dev;
 
                dev_net_set(dev, net);
                dev->rtnl_link_ops = &tun_link_ops;
@@ -2859,8 +2862,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
 err_detach:
        tun_detach_all(dev);
-       /* register_netdevice() already called tun_free_netdev() */
-       goto err_free_dev;
+       /* We are here because register_netdevice() has failed.
+        * If register_netdevice() already called tun_free_netdev()
+        * while dealing with the error, tun->pcpu_stats has been cleared.
+        */
+       if (!tun->pcpu_stats)
+               goto err_free_dev;
 
 err_free_flow:
        tun_flow_uninit(tun);