Commit 1a0f25a5 authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by Tony Nguyen
Browse files

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: fcea6f3d ("ice: Add stats and ethtool support")
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: default avatarGurucharan G <gurucharanx.g@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent de6acd1c
Loading
Loading
Loading
Loading
+18 −11
Original line number Diff line number Diff line
@@ -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);
}

/**