aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_qdio.c
diff options
context:
space:
mode:
authorAndreas Herrmann <aherrman@de.ibm.com>2005-06-13 07:20:35 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-06-13 22:32:48 -0400
commit1db2c9c0931a53fe013db55fd2ff58859db31e8d (patch)
tree1134627ac98d91896dcdb161d5df7ecef60a4de3 /drivers/s390/scsi/zfcp_qdio.c
parent64b29a130901d5b8578e9f602cf2dae56aaff224 (diff)
[SCSI] zfcp: fix bug during adapter shutdown
Fixes a race between zfcp_fsf_req_dismiss_all and zfcp_qdio_reqid_check. During adapter shutdown it occurred that a request was cleaned up twice. First during its normal completion. Second when dismiss_all was called. The fix is to serialize access to fsf request list between zfcp_fsf_req_dismiss_all and zfcp_qdio_reqid_check and delete a fsf request from the list if its completion is triggered. (Additionally a rwlock was replaced by a spinlock and fsf_req_cleanup was eliminated.) 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_qdio.c')
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index fb218dd9d934..24e16ec331d9 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -446,37 +446,37 @@ int
446zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) 446zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
447{ 447{
448 struct zfcp_fsf_req *fsf_req; 448 struct zfcp_fsf_req *fsf_req;
449 int retval = 0;
450 449
451 /* invalid (per convention used in this driver) */ 450 /* invalid (per convention used in this driver) */
452 if (unlikely(!sbale_addr)) { 451 if (unlikely(!sbale_addr)) {
453 ZFCP_LOG_NORMAL("bug: invalid reqid\n"); 452 ZFCP_LOG_NORMAL("bug: invalid reqid\n");
454 retval = -EINVAL; 453 return -EINVAL;
455 goto out;
456 } 454 }
457 455
458 /* valid request id and thus (hopefully :) valid fsf_req address */ 456 /* valid request id and thus (hopefully :) valid fsf_req address */
459 fsf_req = (struct zfcp_fsf_req *) sbale_addr; 457 fsf_req = (struct zfcp_fsf_req *) sbale_addr;
460 458
459 /* serialize with zfcp_fsf_req_dismiss_all */
460 spin_lock(&adapter->fsf_req_list_lock);
461 if (list_empty(&adapter->fsf_req_list_head)) {
462 spin_unlock(&adapter->fsf_req_list_lock);
463 return 0;
464 }
465 list_del(&fsf_req->list);
466 atomic_dec(&adapter->fsf_reqs_active);
467 spin_unlock(&adapter->fsf_req_list_lock);
468
461 if (unlikely(adapter != fsf_req->adapter)) { 469 if (unlikely(adapter != fsf_req->adapter)) {
462 ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, " 470 ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, "
463 "fsf_req->adapter=%p, adapter=%p)\n", 471 "fsf_req->adapter=%p, adapter=%p)\n",
464 fsf_req, fsf_req->adapter, adapter); 472 fsf_req, fsf_req->adapter, adapter);
465 retval = -EINVAL; 473 return -EINVAL;
466 goto out;
467 }
468
469 ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb);
470 if (likely(fsf_req->qtcb)) {
471 ZFCP_LOG_TRACE("hex dump of QTCB:\n");
472 ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb,
473 sizeof(struct fsf_qtcb));
474 } 474 }
475 475
476 /* finish the FSF request */ 476 /* finish the FSF request */
477 zfcp_fsf_req_complete(fsf_req); 477 zfcp_fsf_req_complete(fsf_req);
478 out: 478
479 return retval; 479 return 0;
480} 480}
481 481
482/** 482/**