Currently, the netdev module ref count is not decremented with module_put() when the module is unloaded while fcoe instances are present. To fix this removed reference count on netdev module completely and added functionality to netdev event handling for NETDEV_UNREGISTER events.
This allows fcoe to remove devices cleanly when the netdev module is unloaded so we no longer need to hold a reference count for the netdev module. Signed-off-by: John Fastabend <[email protected]> --- drivers/scsi/fcoe/fcoe.c | 94 +++++++--------------------------------------- 1 files changed, 14 insertions(+), 80 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 03e1926..85e51e9 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -371,14 +371,16 @@ static int fcoe_if_destroy(struct net_device *netdev) fc_exch_mgr_free(lp->emp); /* Delete secondary MAC addresses */ - rtnl_lock(); - memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); - dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN); - if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) - dev_unicast_delete(fc->real_dev, - fc->ctlr.data_src_addr, ETH_ALEN); - dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); - rtnl_unlock(); + if (fc->real_dev->reg_state == NETREG_REGISTERED) { + rtnl_lock(); + memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); + dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN); + if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) + dev_unicast_delete(fc->real_dev, + fc->ctlr.data_src_addr, ETH_ALEN); + dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); + rtnl_unlock(); + } /* Free the per-CPU receive threads */ fcoe_percpu_clean(lp); @@ -1414,6 +1416,10 @@ static int fcoe_device_notification(struct notifier_block *notifier, break; case NETDEV_REGISTER: break; + case NETDEV_UNREGISTER: + fcoe_if_destroy(fc->real_dev); + goto out; + break; default: FC_DBG("Unknown event %ld from netdev netlink\n", event); } @@ -1450,75 +1456,6 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) } /** - * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev - * @netdev: the target netdev - * - * Returns: ptr to the struct module, NULL for failure - */ -static struct module * -fcoe_netdev_to_module_owner(const struct net_device *netdev) -{ - struct device *dev; - - if (!netdev) - return NULL; - - dev = netdev->dev.parent; - if (!dev) - return NULL; - - if (!dev->driver) - return NULL; - - return dev->driver->owner; -} - -/** - * fcoe_ethdrv_get() - Hold the Ethernet driver - * @netdev: the target netdev - * - * Holds the Ethernet driver module by try_module_get() for - * the corresponding netdev. - * - * Returns: 0 for success - */ -static int fcoe_ethdrv_get(const struct net_device *netdev) -{ - struct module *owner; - - owner = fcoe_netdev_to_module_owner(netdev); - if (owner) { - printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n", - module_name(owner), netdev->name); - return try_module_get(owner); - } - return -ENODEV; -} - -/** - * fcoe_ethdrv_put() - Release the Ethernet driver - * @netdev: the target netdev - * - * Releases the Ethernet driver module by module_put for - * the corresponding netdev. - * - * Returns: 0 for success - */ -static int fcoe_ethdrv_put(const struct net_device *netdev) -{ - struct module *owner; - - owner = fcoe_netdev_to_module_owner(netdev); - if (owner) { - printk(KERN_DEBUG "fcoe:release driver module %s for %s\n", - module_name(owner), netdev->name); - module_put(owner); - return 0; - } - return -ENODEV; -} - -/** * fcoe_destroy() - handles the destroy from sysfs * @buffer: expected to be an eth if name * @kp: associated kernel param @@ -1547,7 +1484,6 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) rc = -EIO; goto out_putdev; } - fcoe_ethdrv_put(netdev); rc = 0; out_putdev: dev_put(netdev); @@ -1577,13 +1513,11 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) rc = -EEXIST; goto out_putdev; } - fcoe_ethdrv_get(netdev); rc = fcoe_if_create(netdev); if (rc) { printk(KERN_ERR "fcoe: fcoe_if_create(%s) failed\n", netdev->name); - fcoe_ethdrv_put(netdev); rc = -EIO; goto out_putdev; } _______________________________________________ devel mailing list [email protected] http://www.open-fcoe.org/mailman/listinfo/devel
