diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2010-06-08 03:19:54 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-12 18:51:22 -0400 |
commit | be1f3c2c027cc5ad735df6a45a542ed1db7ec48b (patch) | |
tree | c97815a7cf25ea62e8f3a6b3597cfa8957f40b81 /net | |
parent | d19b51499967baddf4f9f12a0067146c2554527a (diff) |
net: Enable 64-bit net device statistics on 32-bit architectures
Use struct rtnl_link_stats64 as the statistics structure.
On 32-bit architectures, insert 32 bits of padding after/before each
field of struct net_device_stats to make its layout compatible with
struct rtnl_link_stats64. Add an anonymous union in net_device; move
stats into the union and add struct rtnl_link_stats64 stats64.
Add net_device_ops::ndo_get_stats64, implementations of which will
return a pointer to struct rtnl_link_stats64. Drivers that implement
this operation must not update the structure asynchronously.
Change dev_get_stats() to call ndo_get_stats64 if available, and to
return a pointer to struct rtnl_link_stats64. Change callers of
dev_get_stats() accordingly.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/8021q/vlanproc.c | 13 | ||||
-rw-r--r-- | net/core/dev.c | 19 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 12 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 6 |
4 files changed, 27 insertions, 23 deletions
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index afead353e215..df56f5ce887c 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c | |||
@@ -278,8 +278,9 @@ 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 | const struct net_device_stats *stats; | 281 | const struct rtnl_link_stats64 *stats; |
282 | static const char fmt[] = "%30s %12lu\n"; | 282 | static const char fmt[] = "%30s %12lu\n"; |
283 | static const char fmt64[] = "%30s %12llu\n"; | ||
283 | int i; | 284 | int i; |
284 | 285 | ||
285 | if (!is_vlan_dev(vlandev)) | 286 | if (!is_vlan_dev(vlandev)) |
@@ -291,12 +292,12 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) | |||
291 | vlandev->name, dev_info->vlan_id, | 292 | vlandev->name, dev_info->vlan_id, |
292 | (int)(dev_info->flags & 1), vlandev->priv_flags); | 293 | (int)(dev_info->flags & 1), vlandev->priv_flags); |
293 | 294 | ||
294 | seq_printf(seq, fmt, "total frames received", stats->rx_packets); | 295 | seq_printf(seq, fmt64, "total frames received", stats->rx_packets); |
295 | seq_printf(seq, fmt, "total bytes received", stats->rx_bytes); | 296 | seq_printf(seq, fmt64, "total bytes received", stats->rx_bytes); |
296 | seq_printf(seq, fmt, "Broadcast/Multicast Rcvd", stats->multicast); | 297 | seq_printf(seq, fmt64, "Broadcast/Multicast Rcvd", stats->multicast); |
297 | seq_puts(seq, "\n"); | 298 | seq_puts(seq, "\n"); |
298 | seq_printf(seq, fmt, "total frames transmitted", stats->tx_packets); | 299 | seq_printf(seq, fmt64, "total frames transmitted", stats->tx_packets); |
299 | seq_printf(seq, fmt, "total bytes transmitted", stats->tx_bytes); | 300 | seq_printf(seq, fmt64, "total bytes transmitted", stats->tx_bytes); |
300 | seq_printf(seq, fmt, "total headroom inc", | 301 | seq_printf(seq, fmt, "total headroom inc", |
301 | dev_info->cnt_inc_headroom_on_tx); | 302 | dev_info->cnt_inc_headroom_on_tx); |
302 | seq_printf(seq, fmt, "total encap on xmit", | 303 | seq_printf(seq, fmt, "total encap on xmit", |
diff --git a/net/core/dev.c b/net/core/dev.c index 277844901ce3..a1abc10db08a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3701,10 +3701,10 @@ void dev_seq_stop(struct seq_file *seq, void *v) | |||
3701 | 3701 | ||
3702 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) | 3702 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) |
3703 | { | 3703 | { |
3704 | const struct net_device_stats *stats = dev_get_stats(dev); | 3704 | const struct rtnl_link_stats64 *stats = dev_get_stats(dev); |
3705 | 3705 | ||
3706 | seq_printf(seq, "%6s: %7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " | 3706 | seq_printf(seq, "%6s: %7llu %7llu %4llu %4llu %4llu %5llu %10llu %9llu " |
3707 | "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", | 3707 | "%8llu %7llu %4llu %4llu %4llu %5llu %7llu %10llu\n", |
3708 | dev->name, stats->rx_bytes, stats->rx_packets, | 3708 | dev->name, stats->rx_bytes, stats->rx_packets, |
3709 | stats->rx_errors, | 3709 | stats->rx_errors, |
3710 | stats->rx_dropped + stats->rx_missed_errors, | 3710 | stats->rx_dropped + stats->rx_missed_errors, |
@@ -5281,18 +5281,21 @@ EXPORT_SYMBOL(dev_txq_stats_fold); | |||
5281 | * @dev: device to get statistics from | 5281 | * @dev: device to get statistics from |
5282 | * | 5282 | * |
5283 | * Get network statistics from device. The device driver may provide | 5283 | * Get network statistics from device. The device driver may provide |
5284 | * its own method by setting dev->netdev_ops->get_stats; otherwise | 5284 | * its own method by setting dev->netdev_ops->get_stats64 or |
5285 | * the internal statistics structure is used. | 5285 | * dev->netdev_ops->get_stats; otherwise the internal statistics |
5286 | * structure is used. | ||
5286 | */ | 5287 | */ |
5287 | const struct net_device_stats *dev_get_stats(struct net_device *dev) | 5288 | const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev) |
5288 | { | 5289 | { |
5289 | const struct net_device_ops *ops = dev->netdev_ops; | 5290 | const struct net_device_ops *ops = dev->netdev_ops; |
5290 | 5291 | ||
5292 | if (ops->ndo_get_stats64) | ||
5293 | return ops->ndo_get_stats64(dev); | ||
5291 | if (ops->ndo_get_stats) | 5294 | if (ops->ndo_get_stats) |
5292 | return ops->ndo_get_stats(dev); | 5295 | return (struct rtnl_link_stats64 *)ops->ndo_get_stats(dev); |
5293 | 5296 | ||
5294 | dev_txq_stats_fold(dev, &dev->stats); | 5297 | dev_txq_stats_fold(dev, &dev->stats); |
5295 | return &dev->stats; | 5298 | return &dev->stats64; |
5296 | } | 5299 | } |
5297 | EXPORT_SYMBOL(dev_get_stats); | 5300 | EXPORT_SYMBOL(dev_get_stats); |
5298 | 5301 | ||
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 99e7052d7323..ea3bb4c3b87d 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -29,6 +29,7 @@ static const char fmt_hex[] = "%#x\n"; | |||
29 | static const char fmt_long_hex[] = "%#lx\n"; | 29 | static const char fmt_long_hex[] = "%#lx\n"; |
30 | static const char fmt_dec[] = "%d\n"; | 30 | static const char fmt_dec[] = "%d\n"; |
31 | static const char fmt_ulong[] = "%lu\n"; | 31 | static const char fmt_ulong[] = "%lu\n"; |
32 | static const char fmt_u64[] = "%llu\n"; | ||
32 | 33 | ||
33 | static inline int dev_isalive(const struct net_device *dev) | 34 | static inline int dev_isalive(const struct net_device *dev) |
34 | { | 35 | { |
@@ -324,14 +325,13 @@ static ssize_t netstat_show(const struct device *d, | |||
324 | struct net_device *dev = to_net_dev(d); | 325 | struct net_device *dev = to_net_dev(d); |
325 | ssize_t ret = -EINVAL; | 326 | ssize_t ret = -EINVAL; |
326 | 327 | ||
327 | WARN_ON(offset > sizeof(struct net_device_stats) || | 328 | WARN_ON(offset > sizeof(struct rtnl_link_stats64) || |
328 | offset % sizeof(unsigned long) != 0); | 329 | offset % sizeof(u64) != 0); |
329 | 330 | ||
330 | read_lock(&dev_base_lock); | 331 | read_lock(&dev_base_lock); |
331 | if (dev_isalive(dev)) { | 332 | if (dev_isalive(dev)) { |
332 | const struct net_device_stats *stats = dev_get_stats(dev); | 333 | const struct rtnl_link_stats64 *stats = dev_get_stats(dev); |
333 | ret = sprintf(buf, fmt_ulong, | 334 | ret = sprintf(buf, fmt_u64, *(u64 *)(((u8 *) stats) + offset)); |
334 | *(unsigned long *)(((u8 *) stats) + offset)); | ||
335 | } | 335 | } |
336 | read_unlock(&dev_base_lock); | 336 | read_unlock(&dev_base_lock); |
337 | return ret; | 337 | return ret; |
@@ -343,7 +343,7 @@ static ssize_t show_##name(struct device *d, \ | |||
343 | struct device_attribute *attr, char *buf) \ | 343 | struct device_attribute *attr, char *buf) \ |
344 | { \ | 344 | { \ |
345 | return netstat_show(d, attr, buf, \ | 345 | return netstat_show(d, attr, buf, \ |
346 | offsetof(struct net_device_stats, name)); \ | 346 | offsetof(struct rtnl_link_stats64, name)); \ |
347 | } \ | 347 | } \ |
348 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) | 348 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) |
349 | 349 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1a2af24e9e3d..e645778e9b7e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -579,7 +579,7 @@ static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, | |||
579 | } | 579 | } |
580 | 580 | ||
581 | static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | 581 | static void copy_rtnl_link_stats(struct rtnl_link_stats *a, |
582 | const struct net_device_stats *b) | 582 | const struct rtnl_link_stats64 *b) |
583 | { | 583 | { |
584 | a->rx_packets = b->rx_packets; | 584 | a->rx_packets = b->rx_packets; |
585 | a->tx_packets = b->tx_packets; | 585 | a->tx_packets = b->tx_packets; |
@@ -610,7 +610,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
610 | a->tx_compressed = b->tx_compressed; | 610 | a->tx_compressed = b->tx_compressed; |
611 | } | 611 | } |
612 | 612 | ||
613 | static void copy_rtnl_link_stats64(void *v, const struct net_device_stats *b) | 613 | static void copy_rtnl_link_stats64(void *v, const struct rtnl_link_stats64 *b) |
614 | { | 614 | { |
615 | struct rtnl_link_stats64 a; | 615 | struct rtnl_link_stats64 a; |
616 | 616 | ||
@@ -791,7 +791,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
791 | { | 791 | { |
792 | struct ifinfomsg *ifm; | 792 | struct ifinfomsg *ifm; |
793 | struct nlmsghdr *nlh; | 793 | struct nlmsghdr *nlh; |
794 | const struct net_device_stats *stats; | 794 | const struct rtnl_link_stats64 *stats; |
795 | struct nlattr *attr; | 795 | struct nlattr *attr; |
796 | 796 | ||
797 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); | 797 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); |