* [PATCH] bonding: fix race that causes invalid statistics
@ 2008-01-28 23:38 Andy Gospodarek
2008-01-28 23:59 ` Jay Vosburgh
0 siblings, 1 reply; 4+ messages in thread
From: Andy Gospodarek @ 2008-01-28 23:38 UTC (permalink / raw)
To: netdev; +Cc: fubar, csnook
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: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Chris Snook <csnook@redhat.com>
---
bond_main.c | 57 ++++++++++++++++++++++++++++++---------------------------
1 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 49a1982..901de6d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3769,41 +3769,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(net_device_stats));
read_unlock_bh(&bond->lock);
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] bonding: fix race that causes invalid statistics
2008-01-28 23:38 [PATCH] bonding: fix race that causes invalid statistics Andy Gospodarek
@ 2008-01-28 23:59 ` Jay Vosburgh
2008-01-29 0:13 ` Chris Snook
2008-01-29 0:38 ` Andy Gospodarek
0 siblings, 2 replies; 4+ messages in thread
From: Jay Vosburgh @ 2008-01-28 23:59 UTC (permalink / raw)
To: Andy Gospodarek; +Cc: netdev, csnook
Andy Gospodarek <andy@greyhouse.net> wrote:
>+ memcpy(stats,&local_stats,sizeof(net_device_stats));
FYI, this generates a compiler error (missing the word "struct"
in here). Other than not compiling, the patch seems reasonable. I'll
fix it up and include it in the series I'll post tomorrow or so.
-J
---
-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] bonding: fix race that causes invalid statistics
2008-01-28 23:59 ` Jay Vosburgh
@ 2008-01-29 0:13 ` Chris Snook
2008-01-29 0:38 ` Andy Gospodarek
1 sibling, 0 replies; 4+ messages in thread
From: Chris Snook @ 2008-01-29 0:13 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: Andy Gospodarek, netdev
Jay Vosburgh wrote:
> Andy Gospodarek <andy@greyhouse.net> wrote:
>
>> + memcpy(stats,&local_stats,sizeof(net_device_stats));
>
> FYI, this generates a compiler error (missing the word "struct"
> in here). Other than not compiling, the patch seems reasonable. I'll
> fix it up and include it in the series I'll post tomorrow or so.
>
> -J
Looks like Andy sent the draft version by mistake. We did in fact test an
otherwise identical patch, which did fix the bug.
-- Chris
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] bonding: fix race that causes invalid statistics
2008-01-28 23:59 ` Jay Vosburgh
2008-01-29 0:13 ` Chris Snook
@ 2008-01-29 0:38 ` Andy Gospodarek
1 sibling, 0 replies; 4+ messages in thread
From: Andy Gospodarek @ 2008-01-29 0:38 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: netdev, csnook
On Mon, Jan 28, 2008 at 03:59:03PM -0800, Jay Osbourn wrote:
> Andy Gospodarek <andy@greyhouse.net> wrote:
>
> >+ memcpy(stats,&local_stats,sizeof(net_device_stats));
>
> FYI, this generates a compiler error (missing the word "struct"
> in here). Other than not compiling, the patch seems reasonable. I'll
> fix it up and include it in the series I'll post tomorrow or so.
>
> -J
>
Crap. Here's the one I intended to send.
Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Chris Snook <csnook@redhat.com>
---
bond_main.c | 57 ++++++++++++++++++++++++++++++---------------------------
1 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 49a1982..901de6d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3769,41 +3769,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);
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-01-29 0:40 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-28 23:38 [PATCH] bonding: fix race that causes invalid statistics Andy Gospodarek
2008-01-28 23:59 ` Jay Vosburgh
2008-01-29 0:13 ` Chris Snook
2008-01-29 0:38 ` Andy Gospodarek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).