zfcp fixes for 2.6.28-rc6
Subsystems (3)
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
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(strucread_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,
PATCH 2/6 zfcp: Fix opening of wka ports
In reply to Christof SchmittFrom: 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 zfcpif (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 ;
PATCH 3/6 zfcp: returning an ERR_PTR where a NULL value is expected
In reply to Christof SchmittFrom: 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;
PATCH 4/6 zfcp: verify for correct rport state before scanning for SCSI devs
In reply to Christof SchmittFrom: 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);
PATCH 5/6 zfcp: eliminate race between validation and locking
In reply to Christof SchmittFrom: 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_latencstatic 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 );
PATCH 6/6 zfcp: fix deadlock between wq triggered port scan and ERP
In reply to Christof SchmittFrom: 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(strucase 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_adapterint 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 ;