diff --git a/net/core/dev.c b/net/core/dev.c index f2b61111e26d5c5c16d621e548065a8fed15dfcd..5a7f20f7857468aeab6ba56ba391c228a59efc91 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3314,7 +3314,6 @@ void netdev_run_todo(void) continue; } - netdev_unregister_sysfs(dev); dev->reg_state = NETREG_UNREGISTERED; netdev_wait_allrefs(dev); @@ -3325,11 +3324,11 @@ void netdev_run_todo(void) BUG_TRAP(!dev->ip6_ptr); BUG_TRAP(!dev->dn_ptr); - /* It must be the very last action, - * after this 'dev' may point to freed up memory. - */ if (dev->destructor) dev->destructor(dev); + + /* Free network device */ + kobject_put(&dev->dev.kobj); } out: @@ -3480,6 +3479,9 @@ void unregister_netdevice(struct net_device *dev) /* Notifier chain MUST detach us from master device. */ BUG_TRAP(!dev->master); + /* Remove entries from sysfs */ + netdev_unregister_sysfs(dev); + /* Finish processing unregister after unlock */ net_set_todo(dev); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index b21307b15b82d7e09d34101180d9f7131bf1f418..5c19b0646d7a3e09c0284a93686c2d738fc92fd1 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -456,9 +456,15 @@ static struct class net_class = { #endif }; +/* Delete sysfs entries but hold kobject reference until after all + * netdev references are gone. + */ void netdev_unregister_sysfs(struct net_device * net) { - device_del(&(net->dev)); + struct device *dev = &(net->dev); + + kobject_get(&dev->kobj); + device_del(dev); } /* Create sysfs entries for network device. */