aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorRobert Love <robert.w.love@intel.com>2010-02-16 12:15:39 -0800
committerJames Bottomley <James.Bottomley@suse.de>2010-02-17 17:43:45 -0600
commite9ee2cf438066aa02df98db959733e1547432983 (patch)
treee0b2cb3e34fcc01e9be9d5e2d4ec2b8686922222 /drivers/scsi
parent03bf7a5af58e07aa13ea61993f5892f733b6f46d (diff)
[SCSI] fcoe: Only rmmod fcoe.ko if there are no active connections
Currently we're gracefully tearing down each active connection when fcoe.ko is removed. We shouldn't allow the user to destroy connections by removing the module. We should force the user to destroy each connection and then the module can be removed. This patch makes it so a refrerence count on the module is taken each time a fcoe_interface is created. The reference count is dropped when the fcoe_interface is destroyed. This makes it so that module_exit() doesn't get called unless all fcoe_interfaces have been destroyed. This patch leaves the removal of interfaces in the module_exit routine so that if the user does a 'rmmod -f' we'll clean everything up before removing the module. The module_put line was put before the out_putdev goto line because we should only be decrementing the reference count if a fcoe_interface is actually destroyed. If we can't find the netdev or the fcoe_interface then it's assumed that something else has destroyed the fcoe_interface and it would have decremented the reference count at that time. Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/fcoe/fcoe.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 10be9f36a4c..2f47ae7cce9 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -2009,6 +2009,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
fcoe_interface_cleanup(fcoe);
rtnl_unlock();
fcoe_if_destroy(fcoe->ctlr.lp);
+ module_put(THIS_MODULE);
+
out_putdev:
dev_put(netdev);
out_nodev:
@@ -2059,6 +2061,11 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
}
#endif
+ if (!try_module_get(THIS_MODULE)) {
+ rc = -EINVAL;
+ goto out_nomod;
+ }
+
rtnl_lock();
netdev = fcoe_if_to_netdev(buffer);
if (!netdev) {
@@ -2099,17 +2106,24 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
if (!fcoe_link_ok(lport))
fcoe_ctlr_link_up(&fcoe->ctlr);
- rc = 0;
-out_free:
/*
* Release from init in fcoe_interface_create(), on success lport
* should be holding a reference taken in fcoe_if_create().
*/
fcoe_interface_put(fcoe);
+ dev_put(netdev);
+ rtnl_unlock();
+ mutex_unlock(&fcoe_config_mutex);
+
+ return 0;
+out_free:
+ fcoe_interface_put(fcoe);
out_putdev:
dev_put(netdev);
out_nodev:
rtnl_unlock();
+ module_put(THIS_MODULE);
+out_nomod:
mutex_unlock(&fcoe_config_mutex);
return rc;
}