Commit 2f57d497 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

gve: fix gve_get_stats()

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: f5cedc84 ("gve: Add transmit and receive support")
Signed-off-by: default avatarEric 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: default avatarDavid S. Miller <davem@davemloft.net>
parent d3436799
...@@ -41,6 +41,7 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s) ...@@ -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); struct gve_priv *priv = netdev_priv(dev);
unsigned int start; unsigned int start;
u64 packets, bytes;
int ring; int ring;
if (priv->rx) { if (priv->rx) {
...@@ -48,10 +49,12 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s) ...@@ -48,10 +49,12 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
do { do {
start = start =
u64_stats_fetch_begin(&priv->rx[ring].statss); u64_stats_fetch_begin(&priv->rx[ring].statss);
s->rx_packets += priv->rx[ring].rpackets; packets = priv->rx[ring].rpackets;
s->rx_bytes += priv->rx[ring].rbytes; bytes = priv->rx[ring].rbytes;
} while (u64_stats_fetch_retry(&priv->rx[ring].statss, } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
start)); start));
s->rx_packets += packets;
s->rx_bytes += bytes;
} }
} }
if (priv->tx) { if (priv->tx) {
...@@ -59,10 +62,12 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s) ...@@ -59,10 +62,12 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
do { do {
start = start =
u64_stats_fetch_begin(&priv->tx[ring].statss); u64_stats_fetch_begin(&priv->tx[ring].statss);
s->tx_packets += priv->tx[ring].pkt_done; packets = priv->tx[ring].pkt_done;
s->tx_bytes += priv->tx[ring].bytes_done; bytes = priv->tx[ring].bytes_done;
} while (u64_stats_fetch_retry(&priv->tx[ring].statss, } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
start)); start));
s->tx_packets += packets;
s->tx_bytes += bytes;
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment