[Open-FCoE] [PATCH 1/5] fcoe: fix BUG_ON due to list locking

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


We saw a call to fcoe_destroy fail to find the interface in the list and
hit a BUG_ON().

Recode so that the lock is held through the lookup and list_del().

Also fix a missing unlock in an error case of fcoe_if_create().

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


diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index e2f9d0c..598a0c6 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -64,9 +64,9 @@ static void fcoe_clean_pending_queue(struct fc_lport *lp);
 static void fcoe_percpu_clean(struct fc_lport *lp);
 static int fcoe_link_ok(struct fc_lport *lp);
 
+static struct fcoe_softc *fcoe_hostlist_lookup_softc(const struct net_device *);
 static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
 static int fcoe_hostlist_add(const struct fc_lport *);
-static int fcoe_hostlist_remove(const struct fc_lport *);
 
 static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *);
 static int fcoe_device_notification(struct notifier_block *, ulong, void *);
@@ -511,18 +511,20 @@ static int fcoe_if_destroy(struct net_device *netdev)
 
 	FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
 
-	lp = fcoe_hostlist_lookup(netdev);
-	if (!lp)
+	write_lock_bh(&fcoe_hostlist_lock);
+	fc = fcoe_hostlist_lookup_softc(netdev);
+	if (!fc) {
+		write_unlock_bh(&fcoe_hostlist_lock);
 		return -ENODEV;
-
-	fc = lport_priv(lp);
+	}
+	/* Remove the instance from fcoe's list */
+	list_del(&fc->list);
+	write_unlock_bh(&fcoe_hostlist_lock);
+	lp = fc->ctlr.lp;
 
 	/* Logout of the fabric */
 	fc_fabric_logoff(lp);
 
-	/* Remove the instance from fcoe's list */
-	fcoe_hostlist_remove(lp);
-
 	/* clean up netdev configurations */
 	fcoe_netdev_cleanup(fc);
 
@@ -683,6 +685,7 @@ static int fcoe_if_create(struct net_device *netdev)
 	/* lport exch manager allocation */
 	rc = fcoe_em_config(lp);
 	if (rc) {
+		write_unlock(&fcoe_hostlist_lock);
 		FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the "
 				"interface\n");
 		goto out_lp_destroy;
@@ -1848,25 +1851,6 @@ int fcoe_hostlist_add(const struct fc_lport *lp)
 }
 
 /**
- * fcoe_hostlist_remove() - remove a lport from lports list
- * @lp: ptr to the fc_lport to be removed
- *
- * Returns: 0 for success
- */
-int fcoe_hostlist_remove(const struct fc_lport *lp)
-{
-	struct fcoe_softc *fc;
-
-	write_lock_bh(&fcoe_hostlist_lock);
-	fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
-	BUG_ON(!fc);
-	list_del(&fc->list);
-	write_unlock_bh(&fcoe_hostlist_lock);
-
-	return 0;
-}
-
-/**
  * fcoe_init() - fcoe module loading initialization
  *
  * Returns 0 on success, negative on failure





More information about the devel mailing list