From: Hans-Joachim Picht <hpicht@redhat.com> Date: Thu, 3 Apr 2008 15:38:39 +0200 Subject: [s390] zfcp: hold lock on port handle for ELS command Message-id: 20080403133839.GG10542@redhat.com O-Subject: [RHEL5 U3 PATCH 5/7] s390 - zfcp: Hold queue lock when checking port handle for ELS command Bugzilla: 434955 RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com> Description ============ We need to hold the queue-lock when checking whether we still have a valid port handle for the ELS command, i.e whether we can issue this request for this port. If the error recovery is about to close this port, then it competes for the queue-lock. If the close request issued by the error recovery wins, then it is guaranteed that this port has been blocked for other requests. Bugzilla ========= BZ 434955 https://bugzilla.redhat.com/show_bug.cgi?id=434955 Upstream status of the patch: ============================= Patch included in linux-2.6 as git commit 3f0ca62add34010241db682e63bb68ba765bf4a9 Test status: ============ Kernel with patch was built and successfully tested Please ACK. With best regards, Hans diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 3a3f30b..6cc091b 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -457,7 +457,7 @@ zfcp_test_link(struct zfcp_port *port) zfcp_port_get(port); retval = zfcp_erp_adisc(port); - if (retval != 0) { + if (retval != 0 && retval != -EBUSY) { zfcp_port_put(port); ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " "on adapter %s\n ", port->wwpn, diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 92ed66f..9e160f4 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1670,6 +1670,12 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) goto failed_req; } + if (unlikely(!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, + &els->port->status))) { + ret = -EBUSY; + goto port_blocked; + } + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); if (zfcp_use_one_sbal(els->req, els->req_count, els->resp, els->resp_count)){ @@ -1751,6 +1757,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) "0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); goto out; + port_blocked: failed_send: zfcp_fsf_req_free(fsf_req);