ice: safer stats processing

The driver was zeroing live stats that could be fetched by
ndo_get_stats64 at any time. This could result in inconsistent
statistics, and the telltale sign was when reading stats frequently from
/proc/net/dev, the stats would go backwards.

Fix by collecting stats into a local, and delaying when we write to the
structure so it's not incremental.

Fixes: fcea6f3da546 ("ice: Add stats and ethtool support")
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Gurucharan G <gurucharanx.g@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
Jesse Brandeburg 2021-11-12 17:06:02 -08:00 committed by Tony Nguyen
parent de6acd1cdd
commit 1a0f25a52e

View File

@ -5930,14 +5930,15 @@ ice_fetch_u64_stats_per_ring(struct u64_stats_sync *syncp, struct ice_q_stats st
/**
* ice_update_vsi_tx_ring_stats - Update VSI Tx ring stats counters
* @vsi: the VSI to be updated
* @vsi_stats: the stats struct to be updated
* @rings: rings to work on
* @count: number of rings
*/
static void
ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi, struct ice_tx_ring **rings,
u16 count)
ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi,
struct rtnl_link_stats64 *vsi_stats,
struct ice_tx_ring **rings, u16 count)
{
struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats;
u16 i;
for (i = 0; i < count; i++) {
@ -5961,15 +5962,13 @@ ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi, struct ice_tx_ring **rings,
*/
static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
{
struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats;
struct rtnl_link_stats64 *vsi_stats;
u64 pkts, bytes;
int i;
/* reset netdev stats */
vsi_stats->tx_packets = 0;
vsi_stats->tx_bytes = 0;
vsi_stats->rx_packets = 0;
vsi_stats->rx_bytes = 0;
vsi_stats = kzalloc(sizeof(*vsi_stats), GFP_ATOMIC);
if (!vsi_stats)
return;
/* reset non-netdev (extended) stats */
vsi->tx_restart = 0;
@ -5981,7 +5980,8 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
rcu_read_lock();
/* update Tx rings counters */
ice_update_vsi_tx_ring_stats(vsi, vsi->tx_rings, vsi->num_txq);
ice_update_vsi_tx_ring_stats(vsi, vsi_stats, vsi->tx_rings,
vsi->num_txq);
/* update Rx rings counters */
ice_for_each_rxq(vsi, i) {
@ -5996,10 +5996,17 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
/* update XDP Tx rings counters */
if (ice_is_xdp_ena_vsi(vsi))
ice_update_vsi_tx_ring_stats(vsi, vsi->xdp_rings,
ice_update_vsi_tx_ring_stats(vsi, vsi_stats, vsi->xdp_rings,
vsi->num_xdp_txq);
rcu_read_unlock();
vsi->net_stats.tx_packets = vsi_stats->tx_packets;
vsi->net_stats.tx_bytes = vsi_stats->tx_bytes;
vsi->net_stats.rx_packets = vsi_stats->rx_packets;
vsi->net_stats.rx_bytes = vsi_stats->rx_bytes;
kfree(vsi_stats);
}
/**