Commit dfc1d0fe authored by Chris Leech's avatar Chris Leech Committed by James Bottomley

[SCSI] fcoe: add mutex to protect create and destroy

Rather than rely on the hostlist_lock to be held while creating exchange
managers, serialize fcoe instance creation and destruction with a mutex.
This will allow the hostlist addition to be moved out of fcoe_if_create(),
which will simplify NPIV support.
Signed-off-by: default avatarChris Leech <christopher.leech@intel.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 54b649f8
...@@ -55,6 +55,8 @@ module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR); ...@@ -55,6 +55,8 @@ module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \ MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \
"Direct Data Placement (DDP)."); "Direct Data Placement (DDP).");
DEFINE_MUTEX(fcoe_config_mutex);
/* fcoe host list */ /* fcoe host list */
LIST_HEAD(fcoe_hostlist); LIST_HEAD(fcoe_hostlist);
DEFINE_RWLOCK(fcoe_hostlist_lock); DEFINE_RWLOCK(fcoe_hostlist_lock);
...@@ -811,6 +813,7 @@ static int __init fcoe_if_init(void) ...@@ -811,6 +813,7 @@ static int __init fcoe_if_init(void)
int __exit fcoe_if_exit(void) int __exit fcoe_if_exit(void)
{ {
fc_release_transport(scsi_transport_fcoe_sw); fc_release_transport(scsi_transport_fcoe_sw);
scsi_transport_fcoe_sw = NULL;
return 0; return 0;
} }
...@@ -1686,6 +1689,19 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) ...@@ -1686,6 +1689,19 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
struct fc_lport *lport; struct fc_lport *lport;
int rc; int rc;
mutex_lock(&fcoe_config_mutex);
#ifdef CONFIG_FCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
* removed. Module paramter sysfs files are writable before the
* module_init function is called and after module_exit.
*/
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
rc = -ENODEV;
goto out_nodev;
}
#endif
netdev = fcoe_if_to_netdev(buffer); netdev = fcoe_if_to_netdev(buffer);
if (!netdev) { if (!netdev) {
rc = -ENODEV; rc = -ENODEV;
...@@ -1705,6 +1721,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) ...@@ -1705,6 +1721,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
out_putdev: out_putdev:
dev_put(netdev); dev_put(netdev);
out_nodev: out_nodev:
mutex_unlock(&fcoe_config_mutex);
return rc; return rc;
} }
...@@ -1722,6 +1739,19 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) ...@@ -1722,6 +1739,19 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
struct fc_lport *lport; struct fc_lport *lport;
struct net_device *netdev; struct net_device *netdev;
mutex_lock(&fcoe_config_mutex);
#ifdef CONFIG_FCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
* removed. Module paramter sysfs files are writable before the
* module_init function is called and after module_exit.
*/
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
rc = -ENODEV;
goto out_nodev;
}
#endif
netdev = fcoe_if_to_netdev(buffer); netdev = fcoe_if_to_netdev(buffer);
if (!netdev) { if (!netdev) {
rc = -ENODEV; rc = -ENODEV;
...@@ -1768,6 +1798,7 @@ out_free: ...@@ -1768,6 +1798,7 @@ out_free:
out_putdev: out_putdev:
dev_put(netdev); dev_put(netdev);
out_nodev: out_nodev:
mutex_unlock(&fcoe_config_mutex);
return rc; return rc;
} }
...@@ -1971,6 +2002,8 @@ static int __init fcoe_init(void) ...@@ -1971,6 +2002,8 @@ static int __init fcoe_init(void)
int rc = 0; int rc = 0;
struct fcoe_percpu_s *p; struct fcoe_percpu_s *p;
mutex_lock(&fcoe_config_mutex);
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
p = &per_cpu(fcoe_percpu, cpu); p = &per_cpu(fcoe_percpu, cpu);
skb_queue_head_init(&p->fcoe_rx_list); skb_queue_head_init(&p->fcoe_rx_list);
...@@ -1991,13 +2024,14 @@ static int __init fcoe_init(void) ...@@ -1991,13 +2024,14 @@ static int __init fcoe_init(void)
if (rc) if (rc)
goto out_free; goto out_free;
mutex_unlock(&fcoe_config_mutex);
return 0; return 0;
out_free: out_free:
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
fcoe_percpu_thread_destroy(cpu); fcoe_percpu_thread_destroy(cpu);
} }
mutex_unlock(&fcoe_config_mutex);
return rc; return rc;
} }
module_init(fcoe_init); module_init(fcoe_init);
...@@ -2012,6 +2046,8 @@ static void __exit fcoe_exit(void) ...@@ -2012,6 +2046,8 @@ static void __exit fcoe_exit(void)
unsigned int cpu; unsigned int cpu;
struct fcoe_interface *fcoe, *tmp; struct fcoe_interface *fcoe, *tmp;
mutex_lock(&fcoe_config_mutex);
fcoe_dev_cleanup(); fcoe_dev_cleanup();
/* releases the associated fcoe hosts */ /* releases the associated fcoe hosts */
...@@ -2025,5 +2061,7 @@ static void __exit fcoe_exit(void) ...@@ -2025,5 +2061,7 @@ static void __exit fcoe_exit(void)
/* detach from scsi transport */ /* detach from scsi transport */
fcoe_if_exit(); fcoe_if_exit();
mutex_unlock(&fcoe_config_mutex);
} }
module_exit(fcoe_exit); module_exit(fcoe_exit);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment