提交 2439f9eb 编写于 作者: A Andy Gospodarek 提交者: David S. Miller

bonding: fix race that causes invalid statistics

I've seen reports of invalid stats in /proc/net/dev for bonding
interfaces, and found it's a pretty easy problem to reproduce.  Since
the current code zeros the bonding stats when a read is requested and a
pointer to that data is returned to the caller we cannot guarantee that
the caller has completely accessed the data before a successive call to
request the stats zeroes the stats again.

This patch creates a new stack variable to keep track of the updated
stats and copies the data from that variable into the bonding stats
structure.  This ensures that the value for any of the bonding stats
should not incorrectly return zero for any of the bonding statistics.
This does use more stack space and require an extra memcpy, but it seems
like a fair trade-off for consistently correct bonding statistics.
Signed-off-by: NAndy Gospodarek <andy@greyhouse.net>
Signed-off-by: NChris Snook <csnook@redhat.com>
Acked-by: NJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 4fe4763c
......@@ -3775,41 +3775,44 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct net_device_stats *stats = &(bond->stats), *sstats;
struct net_device_stats local_stats;
struct slave *slave;
int i;
memset(stats, 0, sizeof(struct net_device_stats));
memset(&local_stats, 0, sizeof(struct net_device_stats));
read_lock_bh(&bond->lock);
bond_for_each_slave(bond, slave, i) {
sstats = slave->dev->get_stats(slave->dev);
stats->rx_packets += sstats->rx_packets;
stats->rx_bytes += sstats->rx_bytes;
stats->rx_errors += sstats->rx_errors;
stats->rx_dropped += sstats->rx_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;
stats->multicast += sstats->multicast;
stats->collisions += sstats->collisions;
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;
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;
}
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;
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;
local_stats.multicast += sstats->multicast;
local_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;
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;
}
memcpy(stats, &local_stats, sizeof(struct net_device_stats));
read_unlock_bh(&bond->lock);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册