aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-04-14 20:00:08 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-01 15:17:19 -0400
commit70b25f890ce9f0520c64075ce9225a5b020a513e (patch)
treec97c211ee93b11c6ebed99c81979bf81773c18d2 /drivers/scsi/libsas
parent9a908c1aa4d3898f62e2cb8af6936b16503ab3e6 (diff)
[SCSI] fix locking around blk_abort_request()
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> Cc: stable@kernel.org Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libsas')
-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 b00efd19aadb..88f744672576 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -395,11 +395,15 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
395void sas_ata_task_abort(struct sas_task *task) 395void sas_ata_task_abort(struct sas_task *task)
396{ 396{
397 struct ata_queued_cmd *qc = task->uldd_task; 397 struct ata_queued_cmd *qc = task->uldd_task;
398 struct request_queue *q = qc->scsicmd->device->request_queue;
398 struct completion *waiting; 399 struct completion *waiting;
400 unsigned long flags;
399 401
400 /* Bounce SCSI-initiated commands to the SCSI EH */ 402 /* Bounce SCSI-initiated commands to the SCSI EH */
401 if (qc->scsicmd) { 403 if (qc->scsicmd) {
404 spin_lock_irqsave(q->queue_lock, flags);
402 blk_abort_request(qc->scsicmd->request); 405 blk_abort_request(qc->scsicmd->request);
406 spin_unlock_irqrestore(q->queue_lock, flags);
403 scsi_schedule_eh(qc->scsicmd->device->host); 407 scsi_schedule_eh(qc->scsicmd->device->host);
404 return; 408 return;
405 } 409 }
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 2660e1b4569a..822835055cef 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -1030,6 +1030,8 @@ int __sas_task_abort(struct sas_task *task)
1030void sas_task_abort(struct sas_task *task) 1030void sas_task_abort(struct sas_task *task)
1031{ 1031{
1032 struct scsi_cmnd *sc = task->uldd_task; 1032 struct scsi_cmnd *sc = task->uldd_task;
1033 struct request_queue *q = sc->device->request_queue;
1034 unsigned long flags;
1033 1035
1034 /* Escape for libsas internal commands */ 1036 /* Escape for libsas internal commands */
1035 if (!sc) { 1037 if (!sc) {
@@ -1044,7 +1046,9 @@ void sas_task_abort(struct sas_task *task)
1044 return; 1046 return;
1045 } 1047 }
1046 1048
1049 spin_lock_irqsave(q->queue_lock, flags);
1047 blk_abort_request(sc->request); 1050 blk_abort_request(sc->request);
1051 spin_unlock_irqrestore(q->queue_lock, flags);
1048 scsi_schedule_eh(sc->device->host); 1052 scsi_schedule_eh(sc->device->host);
1049} 1053}
1050 1054