Commit 93bd2085 authored by Stephen Hemminger's avatar Stephen Hemminger

[NET]: net-sysfs - use attribute group instead of kobject for statistics.

Net statistics were in a kobject only because there was no better way
to create a directory.  Latest 2.6.0-test3 bk tree, has merged in
Pat's change to provide 'attribute groups'.

This patch converts netdevice's from a statistic's kobject to attribute
group.  This is cleaner and fixes some shutdown unload issues as well.

Ps. it gets rid of of the object
parent 348f2c46
...@@ -463,9 +463,6 @@ struct net_device ...@@ -463,9 +463,6 @@ struct net_device
/* class/net/name entry */ /* class/net/name entry */
struct class_device class_dev; struct class_device class_dev;
/* statistics sub-directory */
struct kobject stats_kobj;
}; };
#define SET_MODULE_OWNER(dev) do { } while (0) #define SET_MODULE_OWNER(dev) do { } while (0)
......
...@@ -188,107 +188,94 @@ static struct class_device_attribute *net_class_attributes[] = { ...@@ -188,107 +188,94 @@ static struct class_device_attribute *net_class_attributes[] = {
NULL NULL
}; };
struct netstat_fs_entry { /* Show a given an attribute in the statistics group */
struct attribute attr; static ssize_t netstat_show(const struct class_device *cd, char *buf,
ssize_t (*show)(const struct net_device_stats *, char *); unsigned long offset)
ssize_t (*store)(struct net_device_stats *, const char *, size_t);
};
static ssize_t net_device_stat_show(unsigned long var, char *buf)
{ {
return sprintf(buf, fmt_ulong, var); struct net_device *dev = to_net_dev(cd);
struct net_device_stats *stats;
ssize_t ret = -EINVAL;
if (offset > sizeof(struct net_device_stats) ||
offset % sizeof(unsigned long) != 0)
WARN_ON(1);
read_lock(&dev_base_lock);
if (dev_isalive(dev) && dev->get_stats &&
(stats = (*dev->get_stats)(dev)))
ret = sprintf(buf, fmt_ulong,
*(unsigned long *)(((u8 *) stats) + offset));
read_unlock(&dev_base_lock);
return ret;
} }
/* generate a read-only statistics attribute */ /* generate a read-only statistics attribute */
#define NETDEVICE_STAT(_NAME) \ #define NETSTAT_ENTRY(name) \
static ssize_t show_stat_##_NAME(const struct net_device_stats *stats, \ static ssize_t show_##name(struct class_device *cd, char *buf) \
char *buf) \
{ \ { \
return net_device_stat_show(stats->_NAME, buf); \ return netstat_show(cd, buf, \
offsetof(struct net_device_stats, name)); \
} \ } \
static struct netstat_fs_entry net_stat_##_NAME = { \ static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
.attr = {.name = __stringify(_NAME), .mode = S_IRUGO }, \
.show = show_stat_##_NAME, \ NETSTAT_ENTRY(rx_packets);
} NETSTAT_ENTRY(tx_packets);
NETSTAT_ENTRY(rx_bytes);
NETDEVICE_STAT(rx_packets); NETSTAT_ENTRY(tx_bytes);
NETDEVICE_STAT(tx_packets); NETSTAT_ENTRY(rx_errors);
NETDEVICE_STAT(rx_bytes); NETSTAT_ENTRY(tx_errors);
NETDEVICE_STAT(tx_bytes); NETSTAT_ENTRY(rx_dropped);
NETDEVICE_STAT(rx_errors); NETSTAT_ENTRY(tx_dropped);
NETDEVICE_STAT(tx_errors); NETSTAT_ENTRY(multicast);
NETDEVICE_STAT(rx_dropped); NETSTAT_ENTRY(collisions);
NETDEVICE_STAT(tx_dropped); NETSTAT_ENTRY(rx_length_errors);
NETDEVICE_STAT(multicast); NETSTAT_ENTRY(rx_over_errors);
NETDEVICE_STAT(collisions); NETSTAT_ENTRY(rx_crc_errors);
NETDEVICE_STAT(rx_length_errors); NETSTAT_ENTRY(rx_frame_errors);
NETDEVICE_STAT(rx_over_errors); NETSTAT_ENTRY(rx_fifo_errors);
NETDEVICE_STAT(rx_crc_errors); NETSTAT_ENTRY(rx_missed_errors);
NETDEVICE_STAT(rx_frame_errors); NETSTAT_ENTRY(tx_aborted_errors);
NETDEVICE_STAT(rx_fifo_errors); NETSTAT_ENTRY(tx_carrier_errors);
NETDEVICE_STAT(rx_missed_errors); NETSTAT_ENTRY(tx_fifo_errors);
NETDEVICE_STAT(tx_aborted_errors); NETSTAT_ENTRY(tx_heartbeat_errors);
NETDEVICE_STAT(tx_carrier_errors); NETSTAT_ENTRY(tx_window_errors);
NETDEVICE_STAT(tx_fifo_errors); NETSTAT_ENTRY(rx_compressed);
NETDEVICE_STAT(tx_heartbeat_errors); NETSTAT_ENTRY(tx_compressed);
NETDEVICE_STAT(tx_window_errors);
NETDEVICE_STAT(rx_compressed); static struct attribute *netstat_attrs[] = {
NETDEVICE_STAT(tx_compressed); &class_device_attr_rx_packets.attr,
&class_device_attr_tx_packets.attr,
static struct attribute *default_attrs[] = { &class_device_attr_rx_bytes.attr,
&net_stat_rx_packets.attr, &class_device_attr_tx_bytes.attr,
&net_stat_tx_packets.attr, &class_device_attr_rx_errors.attr,
&net_stat_rx_bytes.attr, &class_device_attr_tx_errors.attr,
&net_stat_tx_bytes.attr, &class_device_attr_rx_dropped.attr,
&net_stat_rx_errors.attr, &class_device_attr_tx_dropped.attr,
&net_stat_tx_errors.attr, &class_device_attr_multicast.attr,
&net_stat_rx_dropped.attr, &class_device_attr_collisions.attr,
&net_stat_tx_dropped.attr, &class_device_attr_rx_length_errors.attr,
&net_stat_multicast.attr, &class_device_attr_rx_over_errors.attr,
&net_stat_collisions.attr, &class_device_attr_rx_crc_errors.attr,
&net_stat_rx_length_errors.attr, &class_device_attr_rx_frame_errors.attr,
&net_stat_rx_over_errors.attr, &class_device_attr_rx_fifo_errors.attr,
&net_stat_rx_crc_errors.attr, &class_device_attr_rx_missed_errors.attr,
&net_stat_rx_frame_errors.attr, &class_device_attr_tx_aborted_errors.attr,
&net_stat_rx_fifo_errors.attr, &class_device_attr_tx_carrier_errors.attr,
&net_stat_rx_missed_errors.attr, &class_device_attr_tx_fifo_errors.attr,
&net_stat_tx_aborted_errors.attr, &class_device_attr_tx_heartbeat_errors.attr,
&net_stat_tx_carrier_errors.attr, &class_device_attr_tx_window_errors.attr,
&net_stat_tx_fifo_errors.attr, &class_device_attr_rx_compressed.attr,
&net_stat_tx_heartbeat_errors.attr, &class_device_attr_tx_compressed.attr,
&net_stat_tx_window_errors.attr,
&net_stat_rx_compressed.attr,
&net_stat_tx_compressed.attr,
NULL NULL
}; };
static ssize_t static struct attribute_group netstat_group = {
netstat_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) .name = "statistics",
{ .attrs = netstat_attrs,
struct netstat_fs_entry *entry
= container_of(attr, struct netstat_fs_entry, attr);
struct net_device *dev
= to_net_dev(to_class_dev(kobj->parent));
struct net_device_stats *stats;
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
if (dev_isalive(dev) && entry->show && dev->get_stats &&
(stats = (*dev->get_stats)(dev)))
ret = entry->show(stats, buf);
read_unlock(&dev_base_lock);
return ret;
}
static struct sysfs_ops netstat_sysfs_ops = {
.show = netstat_attr_show,
}; };
static struct kobj_type netstat_ktype = {
.sysfs_ops = &netstat_sysfs_ops,
.default_attrs = default_attrs,
};
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
static int netdev_hotplug(struct class_device *cd, char **envp, static int netdev_hotplug(struct class_device *cd, char **envp,
...@@ -339,32 +326,23 @@ int netdev_register_sysfs(struct net_device *net) ...@@ -339,32 +326,23 @@ int netdev_register_sysfs(struct net_device *net)
goto out_unreg; goto out_unreg;
} }
net->stats_kobj.parent = NULL;
if (net->get_stats) {
struct kobject *k = &net->stats_kobj;
k->parent = &class_dev->kobj; if (net->get_stats &&
strlcpy(k->name, "statistics", KOBJ_NAME_LEN); (ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
k->ktype = &netstat_ktype; goto out_unreg;
if((ret = kobject_register(k))) return 0;
goto out_unreg;
}
out:
return ret;
out_unreg: out_unreg:
printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n", printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n",
net->name, ret); net->name, ret);
class_device_unregister(class_dev); class_device_unregister(class_dev);
goto out; out:
return ret;
} }
void netdev_unregister_sysfs(struct net_device *net) void netdev_unregister_sysfs(struct net_device *net)
{ {
if (net->stats_kobj.parent)
kobject_unregister(&net->stats_kobj);
class_device_unregister(&net->class_dev); class_device_unregister(&net->class_dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment