From: Stephen Hemminger Change the initialization of the class device portion of the net device to be done earlier, so that any races before registration completes are harmless. Add a mutex to avoid changes to netdevice during the class device registration. Signed-off-by: Stephen Hemminger Cc: Greg KH Cc: "David S. Miller" Cc: Jeff Garzik Signed-off-by: Andrew Morton --- net/core/dev.c | 10 ++++++++-- net/core/net-sysfs.c | 11 ++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff -puN net/core/dev.c~netdev-hotplug-napi-race-cleanup net/core/dev.c --- devel/net/core/dev.c~netdev-hotplug-napi-race-cleanup 2006-04-24 18:30:56.000000000 -0700 +++ devel-akpm/net/core/dev.c 2006-04-24 18:30:56.000000000 -0700 @@ -203,10 +203,12 @@ DEFINE_PER_CPU(struct softnet_data, soft #ifdef CONFIG_SYSFS extern int netdev_sysfs_init(void); -extern int netdev_register_sysfs(struct net_device *); -extern void netdev_unregister_sysfs(struct net_device *); +extern void netdev_init_classdev(struct net_device *); +#define netdev_register_sysfs(dev) class_device_add(&(dev->class_dev)) +#define netdev_unregister_sysfs(dev) class_device_del(&(dev->class_dev)) #else #define netdev_sysfs_init() (0) +#define netdev_init_classdev(dev) do { } while(0) #define netdev_register_sysfs(dev) (0) #define netdev_unregister_sysfs(dev) do { } while(0) #endif @@ -2870,6 +2872,8 @@ int register_netdevice(struct net_device set_bit(__LINK_STATE_PRESENT, &dev->state); + netdev_init_classdev(dev); + dev->next = NULL; dev_init_scheduler(dev); write_lock_bh(&dev_base_lock); @@ -3043,7 +3047,9 @@ void netdev_run_todo(void) switch(dev->reg_state) { case NETREG_REGISTERING: + rtnl_lock(); err = netdev_register_sysfs(dev); + __rtnl_unlock(); if (err) printk(KERN_ERR "%s: failed sysfs registration (%d)\n", dev->name, err); diff -puN net/core/net-sysfs.c~netdev-hotplug-napi-race-cleanup net/core/net-sysfs.c --- devel/net/core/net-sysfs.c~netdev-hotplug-napi-race-cleanup 2006-04-24 18:30:56.000000000 -0700 +++ devel-akpm/net/core/net-sysfs.c 2006-04-24 18:30:56.000000000 -0700 @@ -443,13 +443,8 @@ static struct class net_class = { #endif }; -void netdev_unregister_sysfs(struct net_device * net) -{ - class_device_del(&(net->class_dev)); -} - -/* Create sysfs entries for network device. */ -int netdev_register_sysfs(struct net_device *net) +/* Setup class device */ +void netdev_init_classdev(struct net_device *net) { struct class_device *class_dev = &(net->class_dev); struct attribute_group **groups = net->sysfs_groups; @@ -470,8 +465,6 @@ int netdev_register_sysfs(struct net_dev || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)) *groups++ = &wireless_group; #endif - - return class_device_add(class_dev); } int netdev_sysfs_init(void) _