aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
authorAndreas Herrmann <aherrman@de.ibm.com>2006-09-18 16:29:20 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-23 19:00:56 -0400
commit4eff4a36516d72e4f6ede901141214a7e05607e7 (patch)
treeb6a775ee5acbfdc91a349fc69580031e17276768 /drivers/s390/scsi
parentdd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6 (diff)
[SCSI] zfcp: fix: use correct req_id in eh_abort_handler
zfcp's eh_abort_handler used the wrong request ID to identify the request to be aborted. The bug was introduced with commit fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3 for improved management of request IDs. The bug is fixed with this patch. Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c4
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c13
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c9
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c63
5 files changed, 42 insertions, 49 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index d2b094d9c34f..504c9219961c 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -189,6 +189,10 @@ struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
189 struct zfcp_fsf_req *request, *tmp; 189 struct zfcp_fsf_req *request, *tmp;
190 unsigned int i; 190 unsigned int i;
191 191
192 /* 0 is reserved as an invalid req_id */
193 if (req_id == 0)
194 return NULL;
195
192 i = req_id % REQUEST_LIST_SIZE; 196 i = req_id % REQUEST_LIST_SIZE;
193 197
194 list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) 198 list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index c033145d0f19..0aa3b1ac76af 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -707,7 +707,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
707 struct zfcp_adapter *adapter, 707 struct zfcp_adapter *adapter,
708 struct scsi_cmnd *scsi_cmnd, 708 struct scsi_cmnd *scsi_cmnd,
709 struct zfcp_fsf_req *fsf_req, 709 struct zfcp_fsf_req *fsf_req,
710 struct zfcp_fsf_req *old_fsf_req) 710 unsigned long old_req_id)
711{ 711{
712 struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf; 712 struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
713 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; 713 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
@@ -768,8 +768,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
768 rec->fsf_seqno = fsf_req->seq_no; 768 rec->fsf_seqno = fsf_req->seq_no;
769 rec->fsf_issued = fsf_req->issued; 769 rec->fsf_issued = fsf_req->issued;
770 } 770 }
771 rec->type.old_fsf_reqid = 771 rec->type.old_fsf_reqid = old_req_id;
772 (unsigned long) old_fsf_req;
773 } else { 772 } else {
774 strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); 773 strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
775 dump->total_size = buflen; 774 dump->total_size = buflen;
@@ -794,17 +793,17 @@ zfcp_scsi_dbf_event_result(const char *tag, int level,
794 struct zfcp_fsf_req *fsf_req) 793 struct zfcp_fsf_req *fsf_req)
795{ 794{
796 _zfcp_scsi_dbf_event_common("rslt", tag, level, 795 _zfcp_scsi_dbf_event_common("rslt", tag, level,
797 adapter, scsi_cmnd, fsf_req, NULL); 796 adapter, scsi_cmnd, fsf_req, 0);
798} 797}
799 798
800inline void 799inline void
801zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, 800zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
802 struct scsi_cmnd *scsi_cmnd, 801 struct scsi_cmnd *scsi_cmnd,
803 struct zfcp_fsf_req *new_fsf_req, 802 struct zfcp_fsf_req *new_fsf_req,
804 struct zfcp_fsf_req *old_fsf_req) 803 unsigned long old_req_id)
805{ 804{
806 _zfcp_scsi_dbf_event_common("abrt", tag, 1, 805 _zfcp_scsi_dbf_event_common("abrt", tag, 1,
807 adapter, scsi_cmnd, new_fsf_req, old_fsf_req); 806 adapter, scsi_cmnd, new_fsf_req, old_req_id);
808} 807}
809 808
810inline void 809inline void
@@ -814,7 +813,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
814 struct zfcp_adapter *adapter = unit->port->adapter; 813 struct zfcp_adapter *adapter = unit->port->adapter;
815 814
816 _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst", 815 _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
817 tag, 1, adapter, scsi_cmnd, NULL, NULL); 816 tag, 1, adapter, scsi_cmnd, NULL, 0);
818} 817}
819 818
820static int 819static int
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 4f4ef0c4ca7b..710ebbf89929 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -185,7 +185,7 @@ extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
185 struct zfcp_fsf_req *); 185 struct zfcp_fsf_req *);
186extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, 186extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
187 struct scsi_cmnd *, struct zfcp_fsf_req *, 187 struct scsi_cmnd *, struct zfcp_fsf_req *,
188 struct zfcp_fsf_req *); 188 unsigned long);
189extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, 189extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
190 struct scsi_cmnd *); 190 struct scsi_cmnd *);
191extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *); 191extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 4913ffbb2fc8..a66b5193b70e 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -3527,7 +3527,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
3527 fsf_req->unit = unit; 3527 fsf_req->unit = unit;
3528 3528
3529 /* associate FSF request with SCSI request (for look up on abort) */ 3529 /* associate FSF request with SCSI request (for look up on abort) */
3530 scsi_cmnd->host_scribble = (char *) fsf_req; 3530 scsi_cmnd->host_scribble = (unsigned char *) fsf_req->req_id;
3531 3531
3532 /* associate SCSI command with FSF request */ 3532 /* associate SCSI command with FSF request */
3533 fsf_req->data = (unsigned long) scsi_cmnd; 3533 fsf_req->data = (unsigned long) scsi_cmnd;
@@ -4667,7 +4667,6 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
4667{ 4667{
4668 volatile struct qdio_buffer_element *sbale; 4668 volatile struct qdio_buffer_element *sbale;
4669 struct zfcp_fsf_req *fsf_req = NULL; 4669 struct zfcp_fsf_req *fsf_req = NULL;
4670 unsigned long flags;
4671 int ret = 0; 4670 int ret = 0;
4672 struct zfcp_qdio_queue *req_queue = &adapter->request_queue; 4671 struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
4673 4672
@@ -4684,10 +4683,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
4684 fsf_req->fsf_command = fsf_cmd; 4683 fsf_req->fsf_command = fsf_cmd;
4685 INIT_LIST_HEAD(&fsf_req->list); 4684 INIT_LIST_HEAD(&fsf_req->list);
4686 4685
4687 /* unique request id */ 4686 /* this is serialized (we are holding req_queue-lock of adapter */
4688 spin_lock_irqsave(&adapter->req_list_lock, flags); 4687 if (adapter->req_no == 0)
4688 adapter->req_no++;
4689 fsf_req->req_id = adapter->req_no++; 4689 fsf_req->req_id = adapter->req_no++;
4690 spin_unlock_irqrestore(&adapter->req_list_lock, flags);
4691 4690
4692 zfcp_fsf_req_qtcb_init(fsf_req); 4691 zfcp_fsf_req_qtcb_init(fsf_req);
4693 4692
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 4857cccb1d5b..043ed7c0a7ed 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -378,16 +378,15 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
378 * will handle late commands. (Usually, the normal completion of late 378 * will handle late commands. (Usually, the normal completion of late
379 * commands is ignored with respect to the running abort operation.) 379 * commands is ignored with respect to the running abort operation.)
380 */ 380 */
381int 381int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
382zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
383{ 382{
384 struct Scsi_Host *scsi_host; 383 struct Scsi_Host *scsi_host;
385 struct zfcp_adapter *adapter; 384 struct zfcp_adapter *adapter;
386 struct zfcp_unit *unit; 385 struct zfcp_unit *unit;
387 int retval = SUCCESS; 386 struct zfcp_fsf_req *fsf_req;
388 struct zfcp_fsf_req *new_fsf_req = NULL;
389 struct zfcp_fsf_req *old_fsf_req;
390 unsigned long flags; 387 unsigned long flags;
388 unsigned long old_req_id;
389 int retval = SUCCESS;
391 390
392 scsi_host = scpnt->device->host; 391 scsi_host = scpnt->device->host;
393 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; 392 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
@@ -399,55 +398,47 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
399 /* avoid race condition between late normal completion and abort */ 398 /* avoid race condition between late normal completion and abort */
400 write_lock_irqsave(&adapter->abort_lock, flags); 399 write_lock_irqsave(&adapter->abort_lock, flags);
401 400
402 /* 401 /* Check whether corresponding fsf_req is still pending */
403 * Check whether command has just completed and can not be aborted. 402 spin_lock(&adapter->req_list_lock);
404 * Even if the command has just been completed late, we can access 403 fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long)
405 * scpnt since the SCSI stack does not release it at least until 404 scpnt->host_scribble);
406 * this routine returns. (scpnt is parameter passed to this routine 405 spin_unlock(&adapter->req_list_lock);
407 * and must not disappear during abort even on late completion.) 406 if (!fsf_req) {
408 */
409 old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
410 if (!old_fsf_req) {
411 write_unlock_irqrestore(&adapter->abort_lock, flags); 407 write_unlock_irqrestore(&adapter->abort_lock, flags);
412 zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL); 408 zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0);
413 retval = SUCCESS; 409 retval = SUCCESS;
414 goto out; 410 goto out;
415 } 411 }
416 old_fsf_req->data = 0; 412 fsf_req->data = 0;
417 old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; 413 fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
414 old_req_id = fsf_req->req_id;
418 415
419 /* don't access old_fsf_req after releasing the abort_lock */ 416 /* don't access old fsf_req after releasing the abort_lock */
420 write_unlock_irqrestore(&adapter->abort_lock, flags); 417 write_unlock_irqrestore(&adapter->abort_lock, flags);
421 /* call FSF routine which does the abort */ 418
422 new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, 419 fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0);
423 adapter, unit, 0); 420 if (!fsf_req) {
424 if (!new_fsf_req) {
425 ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n"); 421 ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
426 zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, 422 zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
427 old_fsf_req); 423 old_req_id);
428 retval = FAILED; 424 retval = FAILED;
429 goto out; 425 goto out;
430 } 426 }
431 427
432 /* wait for completion of abort */ 428 __wait_event(fsf_req->completion_wq,
433 __wait_event(new_fsf_req->completion_wq, 429 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
434 new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
435 430
436 /* status should be valid since signals were not permitted */ 431 if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
437 if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { 432 zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0);
438 zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
439 NULL);
440 retval = SUCCESS; 433 retval = SUCCESS;
441 } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { 434 } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
442 zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req, 435 zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0);
443 NULL);
444 retval = SUCCESS; 436 retval = SUCCESS;
445 } else { 437 } else {
446 zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req, 438 zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0);
447 NULL);
448 retval = FAILED; 439 retval = FAILED;
449 } 440 }
450 zfcp_fsf_req_free(new_fsf_req); 441 zfcp_fsf_req_free(fsf_req);
451 out: 442 out:
452 return retval; 443 return retval;
453} 444}