Skip to contentSkip to conversation

zfcp fixes for 2.6.28-rc6

PATCH New Christof Schmitt 1 participant 7 messages Nov 26, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover zfcp fixes for 2.6.28-rc6

Busy times...

During stress testing we found some more issues in the zfcp driver. The patches apply on top of the current linux-2.6 git tree, please apply.

Thanks,

Christof

#1 lore raw

PATCH 1/6 zfcp: fix remote port status check

From: Martin Petermann <[email protected]>

For an incoming RSCN it was checked by the ZFCP_STATUS_PORT_DID_DID define to re-open a remote port or to test the connection. Since this define was re-used it was also necessary to replace that define with ZFCP_STATUS_PORT_PHYS_OPEN.

---

 drivers/s390/scsi/zfcp_fc.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/s390/scsi/zfcp_fc.c +1 -2
@@ -125,8 +125,7 @@ static void _zfcp_fc_incoming_rscn(struc
 
 	read_lock_irqsave(&zfcp_data.config_lock, flags);
 	list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) {
-		/* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */
-		if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID))
+		if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_PHYS_OPEN))
 			/* Try to connect to unused ports anyway. */
 			zfcp_erp_port_reopen(port,
 					     ZFCP_STATUS_COMMON_ERP_FAILED,
#2 lore raw

PATCH 2/6 zfcp: Fix opening of wka ports

In reply to Christof Schmitt

From: Christof Schmitt <[email protected]>

Running two wka_port_get calls in parallel could issue two open_port requests, overwriting the port handle. Don't issue an open_port for the state PORT_OPENING, and only read the data from GOOD responses.

---
 drivers/s390/scsi/zfcp_fc.c  |    3 ++-
 drivers/s390/scsi/zfcp_fsf.c |    1 +
 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/s390/scsi/zfcp_fc.c +2 -1
@@ -50,7 +50,8 @@ static int zfcp_wka_port_get(struct zfcp
 	if (mutex_lock_interruptible(&wka_port->mutex))
 		return -ERESTARTSYS;
 
-	if (wka_port->status != ZFCP_WKA_PORT_ONLINE) {
+	if (wka_port->status == ZFCP_WKA_PORT_OFFLINE ||
+	    wka_port->status == ZFCP_WKA_PORT_CLOSING) {
 		wka_port->status = ZFCP_WKA_PORT_OPENING;
 		if (zfcp_fsf_open_wka_port(wka_port))
 			wka_port->status = ZFCP_WKA_PORT_OFFLINE;
drivers/s390/scsi/zfcp_fsf.c +1 -0
@@ -1584,6 +1584,7 @@ static void zfcp_fsf_open_wka_port_handl
 		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
 		break;
 	case FSF_PORT_ALREADY_OPEN:
+		break;
 	case FSF_GOOD:
 		wka_port->handle = header->port_handle;
 		wka_port->status = ZFCP_WKA_PORT_ONLINE;
#3 lore raw

PATCH 3/6 zfcp: returning an ERR_PTR where a NULL value is expected

In reply to Christof Schmitt

From: Swen Schillig <[email protected]>

Aborting a SCSI cmnd might requrie to send a abort_fsf_cmnd. If the creation of this fsf_req fails an ERR_PTR is returned where a NULL value would be expected as an error indicator. This ERR_PTR is dereferenced as valid fsf_req in succeeding processing leading to an error.

---
 drivers/s390/scsi/zfcp_fsf.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/s390/scsi/zfcp_fsf.c +6 -2
@@ -930,8 +930,10 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_
 		goto out;
 	req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
 				  req_flags, adapter->pool.fsf_req_abort);
-	if (IS_ERR(req))
+	if (IS_ERR(req)) {
+		req = NULL;
 		goto out;
+	}
 
 	if (unlikely(!(atomic_read(&unit->status) &
 		       ZFCP_STATUS_COMMON_UNBLOCKED)))
@@ -2443,8 +2445,10 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_c
 		goto out;
 	req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
 				  adapter->pool.fsf_req_scsi);
-	if (IS_ERR(req))
+	if (IS_ERR(req)) {
+		req = NULL;
 		goto out;
+	}
 
 	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
 	req->data = unit;
#4 lore raw

PATCH 4/6 zfcp: verify for correct rport state before scanning for SCSI devs

In reply to Christof Schmitt

From: Swen Schillig <[email protected]>

Prevent a SCSI target scan for a rport which have turned invalid in the meantime.

---

 drivers/s390/scsi/zfcp_erp.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/s390/scsi/zfcp_erp.c +3 -1
@@ -1186,7 +1186,9 @@ static void zfcp_erp_scsi_scan(struct wo
 		container_of(work, struct zfcp_erp_add_work, work);
 	struct zfcp_unit *unit = p->unit;
 	struct fc_rport *rport = unit->port->rport;
-	scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
+
+	if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
+		scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
 			 scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
 	atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
 	zfcp_unit_put(unit);
#5 lore raw

PATCH 5/6 zfcp: eliminate race between validation and locking

In reply to Christof Schmitt

From: Swen Schillig <[email protected]>

The check of having a valid pointer was performed before the processing was secured by the lock. Between those two steps the pointer can turn invalid. During further processing another value is used (referenced by the pointer described above) as a function pointer which is never verified to be valid either, resulting under some circumstances in an invalid function call. This patch is fixing both issues.

---

 drivers/s390/scsi/zfcp_fsf.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/s390/scsi/zfcp_fsf.c +7 -4
@@ -2116,18 +2116,21 @@ static inline void zfcp_fsf_trace_latenc
 
 static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
 {
-	struct scsi_cmnd *scpnt = req->data;
+	struct scsi_cmnd *scpnt;
 	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
 	    &(req->qtcb->bottom.io.fcp_rsp);
 	u32 sns_len;
 	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
 	unsigned long flags;
 
-	if (unlikely(!scpnt))
-		return;
-
 	read_lock_irqsave(&req->adapter->abort_lock, flags);
 
+	scpnt = req->data;
+	if (unlikely(!scpnt)) {
+		read_unlock_irqrestore(&req->adapter->abort_lock, flags);
+		return;
+	}
+
 	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) {
 		set_host_byte(scpnt, DID_SOFT_ERROR);
 		set_driver_byte(scpnt, SUGGEST_RETRY);
#6 lore raw

PATCH 6/6 zfcp: fix deadlock between wq triggered port scan and ERP

In reply to Christof Schmitt

From: Swen Schillig <[email protected]>

Waiting for the ERP to be finished in a task running in the global kernel work-queue is a bad idea, especially if the ERP needs to run another job in this work-queue before it can finish. -> deadlock.

This patch removes the necessity to wait for a finished ERP from the scan task and moves the job scheduling to the end of the ERP.

---

 drivers/s390/scsi/zfcp_erp.c |    3 ++-
 drivers/s390/scsi/zfcp_fc.c  |    1 -
 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/s390/scsi/zfcp_erp.c +2 -1
@@ -720,7 +720,6 @@ static int zfcp_erp_adapter_strategy_gen
 		goto failed_openfcp;
 
 	atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &act->adapter->status);
-	schedule_work(&act->adapter->scan_work);
 
 	return ZFCP_ERP_SUCCEEDED;
 
@@ -1284,6 +1283,8 @@ static void zfcp_erp_action_cleanup(stru
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
 		if (result != ZFCP_ERP_SUCCEEDED)
 			zfcp_erp_rports_del(adapter);
+		else
+			schedule_work(&adapter->scan_work);
 		zfcp_adapter_put(adapter);
 		break;
 	}
drivers/s390/scsi/zfcp_fc.c +0 -1
@@ -610,7 +610,6 @@ int zfcp_scan_ports(struct zfcp_adapter 
 	int ret, i;
 	struct zfcp_gpn_ft *gpn_ft;
 
-	zfcp_erp_wait(adapter); /* wait until adapter is finished with ERP */
 	if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
 		return 0;