gve: fix gve_get_stats()
authorEric Dumazet <edumazet@google.com>
Wed, 6 Oct 2021 00:30:30 +0000 (17:30 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 6 Oct 2021 14:11:51 +0000 (15:11 +0100)
gve_get_stats() can report wrong numbers if/when u64_stats_fetch_retry()
returns true.

What is needed here is to sample values in temporary variables,
and only use them after each loop is ended.

Fixes: f5cedc84a30d ("gve: Add transmit and receive support")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Catherine Sullivan <csully@google.com>
Cc: Sagi Shahar <sagis@google.com>
Cc: Jon Olson <jonolson@google.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Luigi Rizzo <lrizzo@google.com>
Cc: Jeroen de Borst <jeroendb@google.com>
Cc: Tao Liu <xliutaox@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/google/gve/gve_main.c

index 29c5f994f92e0f0cb3d1c50937f10b937ac30e7c..1b49e9feacac36f356539a40cdd7a988d22bf406 100644 (file)
@@ -41,6 +41,7 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
 {
        struct gve_priv *priv = netdev_priv(dev);
        unsigned int start;
+       u64 packets, bytes;
        int ring;
 
        if (priv->rx) {
@@ -48,10 +49,12 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
                        do {
                                start =
                                  u64_stats_fetch_begin(&priv->rx[ring].statss);
-                               s->rx_packets += priv->rx[ring].rpackets;
-                               s->rx_bytes += priv->rx[ring].rbytes;
+                               packets = priv->rx[ring].rpackets;
+                               bytes = priv->rx[ring].rbytes;
                        } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
                                                       start));
+                       s->rx_packets += packets;
+                       s->rx_bytes += bytes;
                }
        }
        if (priv->tx) {
@@ -59,10 +62,12 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
                        do {
                                start =
                                  u64_stats_fetch_begin(&priv->tx[ring].statss);
-                               s->tx_packets += priv->tx[ring].pkt_done;
-                               s->tx_bytes += priv->tx[ring].bytes_done;
+                               packets = priv->tx[ring].pkt_done;
+                               bytes = priv->tx[ring].bytes_done;
                        } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
                                                       start));
+                       s->tx_packets += packets;
+                       s->tx_bytes += bytes;
                }
        }
 }