netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.5.70+] Cleanup net-sysfs show and change functions
@ 2003-06-10 20:38 Stephen Hemminger
  2003-06-12  7:00 ` David S. Miller
  0 siblings, 1 reply; 2+ messages in thread
From: Stephen Hemminger @ 2003-06-10 20:38 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev

This cleans up the network sysfs code to use helper functions to unify
the show/change functions, by using common code in functions rather
than template macros.

The function always checks for dead devices, so I/O will fail.

diff -Nru a/net/core/net-sysfs.c b/net/core/net-sysfs.c
--- a/net/core/net-sysfs.c	Tue Jun 10 13:32:42 2003
+++ b/net/core/net-sysfs.c	Tue Jun 10 13:32:42 2003
@@ -3,10 +3,6 @@
  *
  * Copyright (c) 2003 Stephen Hemminber <shemminger@osdl.org>
  * 
- *
- * TODO:
- * last_tx
- * last_rx
  */
 
 #include <linux/config.h>
@@ -16,33 +12,61 @@
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
 
-#define to_net_dev(class) container_of((class), struct net_device, class_dev)
+#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
+#define to_net_dev(class) container_of(class, struct net_device, class_dev)
 
-/* generate a show function for  simple field */
+/* use same locking rules as GIF* ioctl's */
+static ssize_t netdev_show(const struct class_device *cd, char *buf,
+			   ssize_t (*format)(const struct net_device *, char *))
+{
+	struct net_device *net = to_net_dev(cd);
+	ssize_t ret = -EINVAL;
+
+	read_lock(&dev_base_lock);
+	if (!net->deadbeaf)
+		ret = (*format)(net, buf);
+	read_unlock(&dev_base_lock);
+
+	return ret;
+}
+
+/* generate a show function for simple field */
 #define NETDEVICE_SHOW(field, format_string)				\
-static ssize_t show_##field(struct class_device *dev, char *buf)	\
+static ssize_t format_##field(const struct net_device *net, char *buf)	\
 {									\
-	return sprintf(buf, format_string, to_net_dev(dev)->field);	\
+	return sprintf(buf, format_string, net->field);			\
+}									\
+static ssize_t show_##field(struct class_device *cd, char *buf)		\
+{									\
+	return netdev_show(cd, buf, format_##field);			\
 }
 
-/* generate a store function for a field with locking */
-#define NETDEVICE_STORE(field)						\
-static ssize_t 								\
-store_##field(struct class_device *dev, const char *buf, size_t len)	\
-{									\
-	char *endp;							\
-	long new = simple_strtol(buf, &endp, 16);			\
-									\
-	if (endp == buf || new < 0)					\
-		return -EINVAL;						\
-									\
-	if (!capable(CAP_NET_ADMIN))					\
-		return -EPERM;						\
-									\
-	rtnl_lock();							\
-	to_net_dev(dev)->field = new;					\
-	rtnl_unlock();							\
-	return len;							\
+
+/* use same locking and permission rules as SIF* ioctl's */
+static ssize_t netdev_store(struct class_device *dev,
+			    const char *buf, size_t len,
+			    int (*set)(struct net_device *, unsigned long))
+{
+	struct net_device *net = to_net_dev(dev);
+	char *endp;
+	unsigned long new;
+	int ret = -EINVAL;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	new = simple_strtoul(buf, &endp, 0);
+	if (endp == buf)
+		goto err;
+
+	rtnl_lock();
+	if (!net->deadbeaf) {
+		if ((ret = (*set)(net, new)) == 0)
+			ret = len;
+	}
+	rtnl_unlock();
+ err:
+	return ret;
 }
 
 /* generate a read-only network device class attribute */
@@ -56,6 +80,7 @@
 NETDEVICE_ATTR(features, "%#x\n");
 NETDEVICE_ATTR(type, "%d\n");
 
+/* use same locking rules as GIFHWADDR ioctl's */
 static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
 {
 	int i;
@@ -72,12 +97,16 @@
 static ssize_t show_address(struct class_device *dev, char *buf)
 {
 	struct net_device *net = to_net_dev(dev);
+	if (net->deadbeaf)
+		return -EINVAL;
 	return format_addr(buf, net->dev_addr, net->addr_len);
 }
 
 static ssize_t show_broadcast(struct class_device *dev, char *buf)
 {
 	struct net_device *net = to_net_dev(dev);
+	if (net->deadbeaf)
+		return -EINVAL;
 	return format_addr(buf, net->broadcast, net->addr_len);
 }
 
@@ -87,54 +116,45 @@
 /* read-write attributes */
 NETDEVICE_SHOW(mtu, "%d\n");
 
-static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
+static int change_mtu(struct net_device *net, unsigned long new_mtu)
 {
-	char *endp;
-	int new_mtu;
-	int err;
-
-	new_mtu = simple_strtoul(buf, &endp, 10);
-	if (endp == buf) 
-		return -EINVAL;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-	
-	rtnl_lock();
-	err = dev_set_mtu(to_net_dev(dev), new_mtu);
-	rtnl_unlock();
+	return dev_set_mtu(net, (int) new_mtu);
+}
 
-	return err == 0 ? len : err;
+static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
+{
+	return netdev_store(dev, buf, len, change_mtu);
 }
 
 static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu);
 
 NETDEVICE_SHOW(flags, "%#x\n");
 
+static int change_flags(struct net_device *net, unsigned long new_flags)
+{
+	return dev_change_flags(net, (unsigned) new_flags);
+}
+
 static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len)
 {
-	unsigned long new_flags;
-	char *endp;
-	int err = 0;
+	return netdev_store(dev, buf, len, change_flags);
+}
 
-	new_flags = simple_strtoul(buf, &endp, 16);
-	if (endp == buf)
-		return -EINVAL;
+static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
 
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-	
-	rtnl_lock();
-	err = dev_change_flags(to_net_dev(dev), new_flags);
-	rtnl_unlock();
+NETDEVICE_SHOW(tx_queue_len, "%lu\n");
 
-	return err ? err : len;
+static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
+{
+	net->tx_queue_len = new_len;
+	return 0;
 }
 
-static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
+static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len)
+{
+	return netdev_store(dev, buf,len, change_tx_queue_len);
+}
 
-NETDEVICE_SHOW(tx_queue_len, "%lu\n");
-NETDEVICE_STORE(tx_queue_len);
 static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, 
 			 store_tx_queue_len);
 
@@ -237,16 +257,17 @@
 {
 	struct netstat_fs_entry *entry
 		= container_of(attr, struct netstat_fs_entry, attr);
-	struct class_device *class_dev
-		= container_of(kobj->parent, struct class_device, kobj);
 	struct net_device *dev
-		= to_net_dev(class_dev);
-	struct net_device_stats *stats 
-		= dev->get_stats ? dev->get_stats(dev) : NULL;
-
-	if (stats && entry->show) 
-		return entry->show(stats, buf);
-	return -EINVAL;
+		= to_net_dev(to_class_dev(kobj->parent));
+	struct net_device_stats *stats;
+	ssize_t ret = -EINVAL;
+	
+	read_lock(&dev_base_lock);
+	if (!dev->deadbeaf && 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 = {

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH 2.5.70+] Cleanup net-sysfs show and change functions
  2003-06-10 20:38 [PATCH 2.5.70+] Cleanup net-sysfs show and change functions Stephen Hemminger
@ 2003-06-12  7:00 ` David S. Miller
  0 siblings, 0 replies; 2+ messages in thread
From: David S. Miller @ 2003-06-12  7:00 UTC (permalink / raw)
  To: shemminger; +Cc: netdev

   From: Stephen Hemminger <shemminger@osdl.org>
   Date: Tue, 10 Jun 2003 13:38:54 -0700

   This cleans up the network sysfs code to use helper functions to unify
   the show/change functions, by using common code in functions rather
   than template macros.
   
   The function always checks for dead devices, so I/O will fail.
   
Applied, thanks.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-06-12  7:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-06-10 20:38 [PATCH 2.5.70+] Cleanup net-sysfs show and change functions Stephen Hemminger
2003-06-12  7:00 ` David S. Miller

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).