diff options
author | Tejun Heo <tj@kernel.org> | 2010-04-14 20:00:08 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-12 18:03:11 -0400 |
commit | 5a904363da074781118bc161a1149494bf195128 (patch) | |
tree | db91be098f86dcde432b70df86179ad87728ae0e /drivers | |
parent | 3054cd85318d5bcf403352746bda26287b1efe9f (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.c | 4 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 4 |
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, | |||
394 | void sas_ata_task_abort(struct sas_task *task) | 394 | void 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) | |||
1029 | void sas_task_abort(struct sas_task *task) | 1029 | void 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 | ||