[Open-FCoE] [PATCH 4/5] libfc: rework rport blocking during reset or link loss

Chris Leech christopher.leech at intel.com
Thu Sep 25 19:07:53 UTC 2008


This removes the duplication of code from scsi_transport_fc and the SCSI
core, and takes a different approach to dealing with the locking when
trying to delete all remote ports.  While holding the host_lock, all online
rports are moved from the fc_host to a temporary list.  Then the temporary
list is walked and fc_remote_port_delete() is called for each rport.
Finally, the host_lock is held again while the blocked rports are spliced
back onto the fc_host's list.

Signed-off-by: Chris Leech <christopher.leech at intel.com>
---

 drivers/scsi/libfc/fc_ns.c |   50 ++++++++++++++++++--------------------------
 1 files changed, 20 insertions(+), 30 deletions(-)


diff --git a/drivers/scsi/libfc/fc_ns.c b/drivers/scsi/libfc/fc_ns.c
index fc3a6dc..db77742 100644
--- a/drivers/scsi/libfc/fc_ns.c
+++ b/drivers/scsi/libfc/fc_ns.c
@@ -358,49 +358,39 @@ static int fc_ns_restart(struct fc_lport *lp)
 	return 0;
 }
 
-/* unlocked varient of scsi_target_block from scsi_lib.c */
-#include "../scsi_priv.h"
-
-static void __device_block(struct scsi_device *sdev, void *data)
-{
-	scsi_internal_device_block(sdev);
-}
-
-static int __target_block(struct device *dev, void *data)
-{
-	if (scsi_is_target_device(dev))
-		__starget_for_each_device(to_scsi_target(dev),
-					  NULL, __device_block);
-	return 0;
-}
-
-static void __scsi_target_block(struct device *dev)
-{
-	if (scsi_is_target_device(dev))
-		__starget_for_each_device(to_scsi_target(dev),
-					  NULL, __device_block);
-	else
-		device_for_each_child(dev, NULL, __target_block);
-}
-
+/**
+ * fc_block_rports - delete all the remote ports, on reset or link down
+ * @lp: libfc local port instance
+ *
+ * This routine temporarily removes any online remote ports from the fc_host
+ * rport list, then drops the host lock in order to call fc_remote_port_delete()
+ * on each rport in turn, and finally splices the list back onto the fc_host.
+ */
 void fc_block_rports(struct fc_lport *lp)
 {
 	struct Scsi_Host *shost = lp->host;
-	struct fc_rport *rport;
+	struct fc_rport *rport, *next;
 	unsigned long flags;
+	LIST_HEAD(rports);
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+	list_for_each_entry_safe(rport, next, &fc_host_rports(shost), peers) {
 		/* protect the name service remote port */
 		if (rport == lp->dns_rp)
 			continue;
 		if (rport->port_state != FC_PORTSTATE_ONLINE)
 			continue;
-		rport->port_state = FC_PORTSTATE_BLOCKED;
-		rport->flags |= FC_RPORT_DEVLOSS_PENDING;
-		__scsi_target_block(&rport->dev);
+		list_move_tail(&rport->peers, &rports);
 	}
 	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	list_for_each_entry(rport, &rports, peers) {
+		fc_remote_port_delete(rport);
+	}
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	list_splice(&rports, &fc_host_rports(shost));
+	spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
 /*




More information about the devel mailing list