aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-06-08 03:19:54 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-12 18:51:22 -0400
commitbe1f3c2c027cc5ad735df6a45a542ed1db7ec48b (patch)
treec97815a7cf25ea62e8f3a6b3597cfa8957f40b81 /net
parentd19b51499967baddf4f9f12a0067146c2554527a (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.c13
-rw-r--r--net/core/dev.c19
-rw-r--r--net/core/net-sysfs.c12
-rw-r--r--net/core/rtnetlink.c6
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
3702static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) 3702static 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 */
5287const struct net_device_stats *dev_get_stats(struct net_device *dev) 5288const 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}
5297EXPORT_SYMBOL(dev_get_stats); 5300EXPORT_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";
29static const char fmt_long_hex[] = "%#lx\n"; 29static const char fmt_long_hex[] = "%#lx\n";
30static const char fmt_dec[] = "%d\n"; 30static const char fmt_dec[] = "%d\n";
31static const char fmt_ulong[] = "%lu\n"; 31static const char fmt_ulong[] = "%lu\n";
32static const char fmt_u64[] = "%llu\n";
32 33
33static inline int dev_isalive(const struct net_device *dev) 34static 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} \
348static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) 348static 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
581static void copy_rtnl_link_stats(struct rtnl_link_stats *a, 581static 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
613static void copy_rtnl_link_stats64(void *v, const struct net_device_stats *b) 613static 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);