diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-07-07 17:58:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-07-07 17:58:56 -0400 |
commit | 28172739f0a276eb8d6ca917b3974c2edb036da3 (patch) | |
tree | b1dc00cfa20c209992e247c6f73601f609f9ca3b /net/8021q | |
parent | 217d32dc5f299c483ca0d3c8cc6811c72c0339c4 (diff) |
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>
Diffstat (limited to 'net/8021q')
-rw-r--r-- | net/8021q/vlan_dev.c | 6 | ||||
-rw-r--r-- | net/8021q/vlanproc.c | 3 |
2 files changed, 4 insertions, 5 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index c6456cb842fa..7865a4ce5250 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -803,11 +803,9 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev) | |||
803 | return dev_ethtool_get_flags(vlan->real_dev); | 803 | return dev_ethtool_get_flags(vlan->real_dev); |
804 | } | 804 | } |
805 | 805 | ||
806 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev) | 806 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) |
807 | { | 807 | { |
808 | struct rtnl_link_stats64 *stats = &dev->stats64; | 808 | dev_txq_stats_fold(dev, (struct net_device_stats *)stats); |
809 | |||
810 | dev_txq_stats_fold(dev, &dev->stats); | ||
811 | 809 | ||
812 | if (vlan_dev_info(dev)->vlan_rx_stats) { | 810 | if (vlan_dev_info(dev)->vlan_rx_stats) { |
813 | struct vlan_rx_stats *p, accum = {0}; | 811 | struct vlan_rx_stats *p, accum = {0}; |
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index df56f5ce887c..80e280f56686 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c | |||
@@ -278,6 +278,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) | |||
278 | { | 278 | { |
279 | struct net_device *vlandev = (struct net_device *) seq->private; | 279 | struct net_device *vlandev = (struct net_device *) seq->private; |
280 | const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); | 280 | const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); |
281 | struct rtnl_link_stats64 temp; | ||
281 | const struct rtnl_link_stats64 *stats; | 282 | const struct rtnl_link_stats64 *stats; |
282 | static const char fmt[] = "%30s %12lu\n"; | 283 | static const char fmt[] = "%30s %12lu\n"; |
283 | static const char fmt64[] = "%30s %12llu\n"; | 284 | static const char fmt64[] = "%30s %12llu\n"; |
@@ -286,7 +287,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) | |||
286 | if (!is_vlan_dev(vlandev)) | 287 | if (!is_vlan_dev(vlandev)) |
287 | return 0; | 288 | return 0; |
288 | 289 | ||
289 | stats = dev_get_stats(vlandev); | 290 | stats = dev_get_stats(vlandev, &temp); |
290 | seq_printf(seq, | 291 | seq_printf(seq, |
291 | "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", | 292 | "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", |
292 | vlandev->name, dev_info->vlan_id, | 293 | vlandev->name, dev_info->vlan_id, |