Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3236

kernel-2.6.18-194.11.1.el5.src.rpm

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;