diff options
author | Andreas Herrmann <aherrman@de.ibm.com> | 2006-09-18 16:29:20 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-09-23 19:00:56 -0400 |
commit | 4eff4a36516d72e4f6ede901141214a7e05607e7 (patch) | |
tree | b6a775ee5acbfdc91a349fc69580031e17276768 /drivers/s390/scsi/zfcp_scsi.c | |
parent | dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6 (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/zfcp_scsi.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 63 |
1 files changed, 27 insertions, 36 deletions
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 | */ |
381 | int | 381 | int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
382 | zfcp_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 | } |