mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 10:31:33 -04:00
net: hns3: fix data race in hns3_fetch_stats
In hns3_fetch_stats(), ring statistics, protected by u64_stats_sync, are
read and accumulated in ignorance of possible u64_stats_fetch_retry()
events. These statistics are already accumulated by
hns3_ring_stats_update(). Fix this by reading them into a temporary
buffer first.
Fixes: b20d7fe51e ("net: hns3: add some statitics info to tx process")
Signed-off-by: David Yang <mmyangfl@gmail.com>
Link: https://patch.msgid.link/20260119160759.1455950-1-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
a917cd0a23
commit
748a81c8ce
@@ -2529,44 +2529,47 @@ static netdev_features_t hns3_features_check(struct sk_buff *skb,
|
||||
static void hns3_fetch_stats(struct rtnl_link_stats64 *stats,
|
||||
struct hns3_enet_ring *ring, bool is_tx)
|
||||
{
|
||||
struct ring_stats ring_stats;
|
||||
unsigned int start;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&ring->syncp);
|
||||
if (is_tx) {
|
||||
stats->tx_bytes += ring->stats.tx_bytes;
|
||||
stats->tx_packets += ring->stats.tx_pkts;
|
||||
stats->tx_dropped += ring->stats.sw_err_cnt;
|
||||
stats->tx_dropped += ring->stats.tx_vlan_err;
|
||||
stats->tx_dropped += ring->stats.tx_l4_proto_err;
|
||||
stats->tx_dropped += ring->stats.tx_l2l3l4_err;
|
||||
stats->tx_dropped += ring->stats.tx_tso_err;
|
||||
stats->tx_dropped += ring->stats.over_max_recursion;
|
||||
stats->tx_dropped += ring->stats.hw_limitation;
|
||||
stats->tx_dropped += ring->stats.copy_bits_err;
|
||||
stats->tx_dropped += ring->stats.skb2sgl_err;
|
||||
stats->tx_dropped += ring->stats.map_sg_err;
|
||||
stats->tx_errors += ring->stats.sw_err_cnt;
|
||||
stats->tx_errors += ring->stats.tx_vlan_err;
|
||||
stats->tx_errors += ring->stats.tx_l4_proto_err;
|
||||
stats->tx_errors += ring->stats.tx_l2l3l4_err;
|
||||
stats->tx_errors += ring->stats.tx_tso_err;
|
||||
stats->tx_errors += ring->stats.over_max_recursion;
|
||||
stats->tx_errors += ring->stats.hw_limitation;
|
||||
stats->tx_errors += ring->stats.copy_bits_err;
|
||||
stats->tx_errors += ring->stats.skb2sgl_err;
|
||||
stats->tx_errors += ring->stats.map_sg_err;
|
||||
} else {
|
||||
stats->rx_bytes += ring->stats.rx_bytes;
|
||||
stats->rx_packets += ring->stats.rx_pkts;
|
||||
stats->rx_dropped += ring->stats.l2_err;
|
||||
stats->rx_errors += ring->stats.l2_err;
|
||||
stats->rx_errors += ring->stats.l3l4_csum_err;
|
||||
stats->rx_crc_errors += ring->stats.l2_err;
|
||||
stats->multicast += ring->stats.rx_multicast;
|
||||
stats->rx_length_errors += ring->stats.err_pkt_len;
|
||||
}
|
||||
ring_stats = ring->stats;
|
||||
} while (u64_stats_fetch_retry(&ring->syncp, start));
|
||||
|
||||
if (is_tx) {
|
||||
stats->tx_bytes += ring_stats.tx_bytes;
|
||||
stats->tx_packets += ring_stats.tx_pkts;
|
||||
stats->tx_dropped += ring_stats.sw_err_cnt;
|
||||
stats->tx_dropped += ring_stats.tx_vlan_err;
|
||||
stats->tx_dropped += ring_stats.tx_l4_proto_err;
|
||||
stats->tx_dropped += ring_stats.tx_l2l3l4_err;
|
||||
stats->tx_dropped += ring_stats.tx_tso_err;
|
||||
stats->tx_dropped += ring_stats.over_max_recursion;
|
||||
stats->tx_dropped += ring_stats.hw_limitation;
|
||||
stats->tx_dropped += ring_stats.copy_bits_err;
|
||||
stats->tx_dropped += ring_stats.skb2sgl_err;
|
||||
stats->tx_dropped += ring_stats.map_sg_err;
|
||||
stats->tx_errors += ring_stats.sw_err_cnt;
|
||||
stats->tx_errors += ring_stats.tx_vlan_err;
|
||||
stats->tx_errors += ring_stats.tx_l4_proto_err;
|
||||
stats->tx_errors += ring_stats.tx_l2l3l4_err;
|
||||
stats->tx_errors += ring_stats.tx_tso_err;
|
||||
stats->tx_errors += ring_stats.over_max_recursion;
|
||||
stats->tx_errors += ring_stats.hw_limitation;
|
||||
stats->tx_errors += ring_stats.copy_bits_err;
|
||||
stats->tx_errors += ring_stats.skb2sgl_err;
|
||||
stats->tx_errors += ring_stats.map_sg_err;
|
||||
} else {
|
||||
stats->rx_bytes += ring_stats.rx_bytes;
|
||||
stats->rx_packets += ring_stats.rx_pkts;
|
||||
stats->rx_dropped += ring_stats.l2_err;
|
||||
stats->rx_errors += ring_stats.l2_err;
|
||||
stats->rx_errors += ring_stats.l3l4_csum_err;
|
||||
stats->rx_crc_errors += ring_stats.l2_err;
|
||||
stats->multicast += ring_stats.rx_multicast;
|
||||
stats->rx_length_errors += ring_stats.err_pkt_len;
|
||||
}
|
||||
}
|
||||
|
||||
static void hns3_nic_get_stats64(struct net_device *netdev,
|
||||
|
||||
Reference in New Issue
Block a user