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 <[email protected]>
---
 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


_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to