net: fix 64 bit counters on 32 bit arches
There is a small possibility that a reader gets incorrect values on 32 bit arches. SNMP applications could catch incorrect counters when a 32bit high part is changed by another stats consumer/provider. One way to solve this is to add a rtnl_link_stats64 param to all ndo_get_stats64() methods, and also add such a parameter to dev_get_stats(). Rule is that we are not allowed to use dev->stats64 as a temporary storage for 64bit stats, but a caller provided area (usually on stack) Old drivers (only providing get_stats() method) need no changes. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Esse commit está contido em:
@@ -3804,51 +3804,49 @@ static int bond_close(struct net_device *bond_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev)
|
||||
static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct bonding *bond = netdev_priv(bond_dev);
|
||||
struct rtnl_link_stats64 *stats = &bond_dev->stats64;
|
||||
struct rtnl_link_stats64 local_stats;
|
||||
struct rtnl_link_stats64 temp;
|
||||
struct slave *slave;
|
||||
int i;
|
||||
|
||||
memset(&local_stats, 0, sizeof(local_stats));
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
|
||||
read_lock_bh(&bond->lock);
|
||||
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
const struct rtnl_link_stats64 *sstats =
|
||||
dev_get_stats(slave->dev);
|
||||
dev_get_stats(slave->dev, &temp);
|
||||
|
||||
local_stats.rx_packets += sstats->rx_packets;
|
||||
local_stats.rx_bytes += sstats->rx_bytes;
|
||||
local_stats.rx_errors += sstats->rx_errors;
|
||||
local_stats.rx_dropped += sstats->rx_dropped;
|
||||
stats->rx_packets += sstats->rx_packets;
|
||||
stats->rx_bytes += sstats->rx_bytes;
|
||||
stats->rx_errors += sstats->rx_errors;
|
||||
stats->rx_dropped += sstats->rx_dropped;
|
||||
|
||||
local_stats.tx_packets += sstats->tx_packets;
|
||||
local_stats.tx_bytes += sstats->tx_bytes;
|
||||
local_stats.tx_errors += sstats->tx_errors;
|
||||
local_stats.tx_dropped += sstats->tx_dropped;
|
||||
stats->tx_packets += sstats->tx_packets;
|
||||
stats->tx_bytes += sstats->tx_bytes;
|
||||
stats->tx_errors += sstats->tx_errors;
|
||||
stats->tx_dropped += sstats->tx_dropped;
|
||||
|
||||
local_stats.multicast += sstats->multicast;
|
||||
local_stats.collisions += sstats->collisions;
|
||||
stats->multicast += sstats->multicast;
|
||||
stats->collisions += sstats->collisions;
|
||||
|
||||
local_stats.rx_length_errors += sstats->rx_length_errors;
|
||||
local_stats.rx_over_errors += sstats->rx_over_errors;
|
||||
local_stats.rx_crc_errors += sstats->rx_crc_errors;
|
||||
local_stats.rx_frame_errors += sstats->rx_frame_errors;
|
||||
local_stats.rx_fifo_errors += sstats->rx_fifo_errors;
|
||||
local_stats.rx_missed_errors += sstats->rx_missed_errors;
|
||||
stats->rx_length_errors += sstats->rx_length_errors;
|
||||
stats->rx_over_errors += sstats->rx_over_errors;
|
||||
stats->rx_crc_errors += sstats->rx_crc_errors;
|
||||
stats->rx_frame_errors += sstats->rx_frame_errors;
|
||||
stats->rx_fifo_errors += sstats->rx_fifo_errors;
|
||||
stats->rx_missed_errors += sstats->rx_missed_errors;
|
||||
|
||||
local_stats.tx_aborted_errors += sstats->tx_aborted_errors;
|
||||
local_stats.tx_carrier_errors += sstats->tx_carrier_errors;
|
||||
local_stats.tx_fifo_errors += sstats->tx_fifo_errors;
|
||||
local_stats.tx_heartbeat_errors += sstats->tx_heartbeat_errors;
|
||||
local_stats.tx_window_errors += sstats->tx_window_errors;
|
||||
stats->tx_aborted_errors += sstats->tx_aborted_errors;
|
||||
stats->tx_carrier_errors += sstats->tx_carrier_errors;
|
||||
stats->tx_fifo_errors += sstats->tx_fifo_errors;
|
||||
stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
|
||||
stats->tx_window_errors += sstats->tx_window_errors;
|
||||
}
|
||||
|
||||
memcpy(stats, &local_stats, sizeof(struct net_device_stats));
|
||||
|
||||
read_unlock_bh(&bond->lock);
|
||||
|
||||
return stats;
|
||||
|
Referência em uma nova issue
Block a user