From: Hans-Joachim Picht <hpicht@redhat.com> Date: Fri, 11 Apr 2008 17:35:07 +0200 Subject: [s390] zfcp: hold lock on port/unit handle for FCP cmd Message-id: 20080411153507.GA29490@blc4eb509856389.ibm.com O-Subject: Re: [RHEL5 U3 PATCH 4/7] s390 - zfcp: Hold queue lock when checking port/unit handle for FCP command Bugzilla: 433537 RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com> Description ============ We need to hold the queue-lock when checking whether we still have a valid unit/port handle for the FCP command, i.e whether we can issue this request for this unit/port. If the error recovery is about to close this unit/port, then it competes for the queue-lock. If the close request issued by the error recovery wins, then it is guaranteed that this unit/port has been blocked for other requests. Bugzilla ========= BZ 433537 https://bugzilla.redhat.com/show_bug.cgi?id=433537 Upstream status of the patch: ============================= Included in linux-2.6 as git commit ba1724202aafed4bbc4a239ac6fb433f454fddea Test status: ============ Kernel with patch was built and successfully tested Here is the feedback I received from the author of the patch based on your comments. ---cut--- This is a bug which is fixed in the updated patch below. The patch implements an additional action to free a resource in case of an error. The problem here is the fact that the zfcp code is a mess. We are currently working on a huge code cleanup. In the process of fixing current problems we tend to provide fixes which try not to change the existing code too heavily. ---cut--- With best regards, Hans diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 59edf96..92ed66f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -3494,6 +3494,12 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, goto failed_req_create; } + if (unlikely(!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, + &unit->status))) { + retval = -EBUSY; + goto unit_blocked; + } + zfcp_unit_get(unit); fsf_req->unit = unit; @@ -3635,6 +3641,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, no_fit: failed_scsi_cmnd: zfcp_unit_put(unit); + unit_blocked: zfcp_fsf_req_free(fsf_req); fsf_req = NULL; scsi_cmnd->host_scribble = NULL; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 40f385c..2139c8f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -261,8 +261,9 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, goto out; } - if (unlikely( - !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))) { + tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, use_timer, + ZFCP_REQ_AUTO_CLEANUP); + if (unlikely(tmp == -EBUSY)) { ZFCP_LOG_DEBUG("adapter %s not ready or unit 0x%016Lx " "on port 0x%016Lx in recovery\n", zfcp_get_busid_by_unit(unit), @@ -271,9 +272,6 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, goto out; } - tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, use_timer, - ZFCP_REQ_AUTO_CLEANUP); - if (unlikely(tmp < 0)) { ZFCP_LOG_DEBUG("error: initiation of Send FCP Cmnd failed\n"); retval = SCSI_MLQUEUE_HOST_BUSY;