aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-04-14 20:00:08 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-12 18:03:11 -0400
commit5a904363da074781118bc161a1149494bf195128 (patch)
treedb91be098f86dcde432b70df86179ad87728ae0e /drivers
parent3054cd85318d5bcf403352746bda26287b1efe9f (diff)
SCSI: fix locking around blk_abort_request()
commit 70b25f890ce9f0520c64075ce9225a5b020a513e upstream. blk_abort_request() expects queue lock to be held by the caller. Grab it before calling the function. Lack of this synchronization led to infinite loop on corrupt q->timeout_list. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: James Bottomley <James.Bottomley@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libsas/sas_ata.c4
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c4
2 files changed, 8 insertions, 0 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index e15501170698..816ab97eb16d 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -394,11 +394,15 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
394void sas_ata_task_abort(struct sas_task *task) 394void sas_ata_task_abort(struct sas_task *task)
395{ 395{
396 struct ata_queued_cmd *qc = task->uldd_task; 396 struct ata_queued_cmd *qc = task->uldd_task;
397 struct request_queue *q = qc->scsicmd->device->request_queue;
397 struct completion *waiting; 398 struct completion *waiting;
399 unsigned long flags;
398 400
399 /* Bounce SCSI-initiated commands to the SCSI EH */ 401 /* Bounce SCSI-initiated commands to the SCSI EH */
400 if (qc->scsicmd) { 402 if (qc->scsicmd) {
403 spin_lock_irqsave(q->queue_lock, flags);
401 blk_abort_request(qc->scsicmd->request); 404 blk_abort_request(qc->scsicmd->request);
405 spin_unlock_irqrestore(q->queue_lock, flags);
402 scsi_schedule_eh(qc->scsicmd->device->host); 406 scsi_schedule_eh(qc->scsicmd->device->host);
403 return; 407 return;
404 } 408 }
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 14b13196b22d..b672d10e2a90 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -1029,6 +1029,8 @@ int __sas_task_abort(struct sas_task *task)
1029void sas_task_abort(struct sas_task *task) 1029void sas_task_abort(struct sas_task *task)
1030{ 1030{
1031 struct scsi_cmnd *sc = task->uldd_task; 1031 struct scsi_cmnd *sc = task->uldd_task;
1032 struct request_queue *q = sc->device->request_queue;
1033 unsigned long flags;
1032 1034
1033 /* Escape for libsas internal commands */ 1035 /* Escape for libsas internal commands */
1034 if (!sc) { 1036 if (!sc) {
@@ -1043,7 +1045,9 @@ void sas_task_abort(struct sas_task *task)
1043 return; 1045 return;
1044 } 1046 }
1045 1047
1048 spin_lock_irqsave(q->queue_lock, flags);
1046 blk_abort_request(sc->request); 1049 blk_abort_request(sc->request);
1050 spin_unlock_irqrestore(q->queue_lock, flags);
1047 scsi_schedule_eh(sc->device->host); 1051 scsi_schedule_eh(sc->device->host);
1048} 1052}
1049 1053