[Open-FCoE] [PATCH 4/5] fcoe: lock entire create / delete process to avoid races

Joe Eykholt jeykholt at cisco.com
Tue Jul 7 23:59:28 UTC 2009


To avoid races and lock-ups where multiple threads are
deleting interfaces, hold a mutex over the entire
create or delete operation.

This is in reaction to a problem seen where one thread
could be deleting an instance, having taken it off the
list already, but not to the point of deleting the scsi_host
and transport attributes yet, and another thread is
in fcoe_exit from rmmod, and reached a BUG() in
fc_release_transport() because of the undeleted instance.

Note that the existing fcoe_hostlist_lock is left as
a r/w lock and held only over list changes so it can
be used in the netdev notification.  Otherwise we'd
have a deadlock with the netdev rtnl_mutex.

Signed-off-by: Joe Eykholt <jeykholt at cisco.com>
---
 drivers/scsi/fcoe/fcoe.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)


diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 91edf2d..da321e0 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -52,6 +52,7 @@ MODULE_LICENSE("GPL v2");
 /* fcoe host list */
 LIST_HEAD(fcoe_hostlist);
 DEFINE_RWLOCK(fcoe_hostlist_lock);
+DEFINE_MUTEX(fcoe_config_mutex);
 DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
 
 /* Function Prototypes */
@@ -1602,6 +1603,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 	struct fcoe_softc *fc;
 	struct net_device *netdev;
 
+	mutex_lock(&fcoe_config_mutex);
 	netdev = fcoe_if_to_netdev(buffer);
 	if (!netdev) {
 		rc = -ENODEV;
@@ -1625,6 +1627,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 out_putdev:
 	dev_put(netdev);
 out_nodev:
+	mutex_unlock(&fcoe_config_mutex);
 	return rc;
 }
 
@@ -1640,6 +1643,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	int rc;
 	struct net_device *netdev;
 
+	mutex_lock(&fcoe_config_mutex);
 	netdev = fcoe_if_to_netdev(buffer);
 	if (!netdev) {
 		rc = -ENODEV;
@@ -1664,6 +1668,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 out_putdev:
 	dev_put(netdev);
 out_nodev:
+	mutex_unlock(&fcoe_config_mutex);
 	return rc;
 }
 
@@ -1849,6 +1854,7 @@ static int __init fcoe_init(void)
 	INIT_LIST_HEAD(&fcoe_hostlist);
 	rwlock_init(&fcoe_hostlist_lock);
 
+	mutex_lock(&fcoe_config_mutex);
 	for_each_possible_cpu(cpu) {
 		p = &per_cpu(fcoe_percpu, cpu);
 		skb_queue_head_init(&p->fcoe_rx_list);
@@ -1867,6 +1873,7 @@ static int __init fcoe_init(void)
 
 	fcoe_if_init();
 
+	mutex_unlock(&fcoe_config_mutex);
 	return 0;
 
 out_free:
@@ -1874,6 +1881,7 @@ out_free:
 		fcoe_percpu_thread_destroy(cpu);
 	}
 
+	mutex_unlock(&fcoe_config_mutex);
 	return rc;
 }
 module_init(fcoe_init);
@@ -1889,6 +1897,7 @@ static void __exit fcoe_exit(void)
 	struct fcoe_softc *fc, *tmp;
 	LIST_HEAD(local_list);
 
+	mutex_lock(&fcoe_config_mutex);
 	fcoe_dev_cleanup();
 
 	write_lock_bh(&fcoe_hostlist_lock);
@@ -1907,5 +1916,6 @@ static void __exit fcoe_exit(void)
 
 	/* detach from scsi transport */
 	fcoe_if_exit();
+	mutex_unlock(&fcoe_config_mutex);
 }
 module_exit(fcoe_exit);





More information about the devel mailing list