aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-05-06 20:56:03 -0400
committerDavid S. Miller <davem@davemloft.net>2006-05-06 20:56:03 -0400
commitfe9925b551a95fae6ec61470c79f8b701a2fe928 (patch)
tree3df1817dee3c804d155e3a1c52b6ff696bc60293
parent1498221d51a43d5fa1a580618591497d90f957d9 (diff)
[NET]: Create netdev attribute_groups with class_device_add
Atomically create attributes when class device is added. This avoids the race between registering class_device (which generates hotplug event), and the creation of attribute groups. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--net/core/dev.c2
-rw-r--r--net/core/net-sysfs.c49
3 files changed, 15 insertions, 38 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 01db7b88a2b1..309f9190a922 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -506,6 +506,8 @@ struct net_device
506 506
507 /* class/net/name entry */ 507 /* class/net/name entry */
508 struct class_device class_dev; 508 struct class_device class_dev;
509 /* space for optional statistics and wireless sysfs groups */
510 struct attribute_group *sysfs_groups[3];
509}; 511};
510 512
511#define NETDEV_ALIGN 32 513#define NETDEV_ALIGN 32
diff --git a/net/core/dev.c b/net/core/dev.c
index 3bad1afc89fa..9ab3cfa58466 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3043,11 +3043,11 @@ void netdev_run_todo(void)
3043 3043
3044 switch(dev->reg_state) { 3044 switch(dev->reg_state) {
3045 case NETREG_REGISTERING: 3045 case NETREG_REGISTERING:
3046 dev->reg_state = NETREG_REGISTERED;
3047 err = netdev_register_sysfs(dev); 3046 err = netdev_register_sysfs(dev);
3048 if (err) 3047 if (err)
3049 printk(KERN_ERR "%s: failed sysfs registration (%d)\n", 3048 printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
3050 dev->name, err); 3049 dev->name, err);
3050 dev->reg_state = NETREG_REGISTERED;
3051 break; 3051 break;
3052 3052
3053 case NETREG_UNREGISTERING: 3053 case NETREG_UNREGISTERING:
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index c12990c9c603..47a6fceb6771 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -29,7 +29,7 @@ static const char fmt_ulong[] = "%lu\n";
29 29
30static inline int dev_isalive(const struct net_device *dev) 30static inline int dev_isalive(const struct net_device *dev)
31{ 31{
32 return dev->reg_state == NETREG_REGISTERED; 32 return dev->reg_state <= NETREG_REGISTERED;
33} 33}
34 34
35/* use same locking rules as GIF* ioctl's */ 35/* use same locking rules as GIF* ioctl's */
@@ -445,58 +445,33 @@ static struct class net_class = {
445 445
446void netdev_unregister_sysfs(struct net_device * net) 446void netdev_unregister_sysfs(struct net_device * net)
447{ 447{
448 struct class_device * class_dev = &(net->class_dev); 448 class_device_del(&(net->class_dev));
449
450 if (net->get_stats)
451 sysfs_remove_group(&class_dev->kobj, &netstat_group);
452
453#ifdef WIRELESS_EXT
454 if (net->get_wireless_stats || (net->wireless_handlers &&
455 net->wireless_handlers->get_wireless_stats))
456 sysfs_remove_group(&class_dev->kobj, &wireless_group);
457#endif
458 class_device_del(class_dev);
459
460} 449}
461 450
462/* Create sysfs entries for network device. */ 451/* Create sysfs entries for network device. */
463int netdev_register_sysfs(struct net_device *net) 452int netdev_register_sysfs(struct net_device *net)
464{ 453{
465 struct class_device *class_dev = &(net->class_dev); 454 struct class_device *class_dev = &(net->class_dev);
466 int ret; 455 struct attribute_group **groups = net->sysfs_groups;
467 456
457 class_device_initialize(class_dev);
468 class_dev->class = &net_class; 458 class_dev->class = &net_class;
469 class_dev->class_data = net; 459 class_dev->class_data = net;
460 class_dev->groups = groups;
470 461
462 BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
471 strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE); 463 strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE);
472 if ((ret = class_device_register(class_dev)))
473 goto out;
474 464
475 if (net->get_stats && 465 if (net->get_stats)
476 (ret = sysfs_create_group(&class_dev->kobj, &netstat_group))) 466 *groups++ = &netstat_group;
477 goto out_unreg;
478 467
479#ifdef WIRELESS_EXT 468#ifdef WIRELESS_EXT
480 if (net->get_wireless_stats || (net->wireless_handlers && 469 if (net->get_wireless_stats
481 net->wireless_handlers->get_wireless_stats)) { 470 || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats))
482 ret = sysfs_create_group(&class_dev->kobj, &wireless_group); 471 *groups++ = &wireless_group;
483 if (ret)
484 goto out_cleanup;
485 }
486 return 0;
487out_cleanup:
488 if (net->get_stats)
489 sysfs_remove_group(&class_dev->kobj, &netstat_group);
490#else
491 return 0;
492#endif 472#endif
493 473
494out_unreg: 474 return class_device_add(class_dev);
495 printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n",
496 net->name, ret);
497 class_device_unregister(class_dev);
498out:
499 return ret;
500} 475}
501 476
502int netdev_sysfs_init(void) 477int netdev_sysfs_init(void)