| From 70b25f890ce9f0520c64075ce9225a5b020a513e Mon Sep 17 00:00:00 2001 |
| From: Tejun Heo <tj@kernel.org> |
| Date: Thu, 15 Apr 2010 09:00:08 +0900 |
| Subject: SCSI: fix locking around blk_abort_request() |
| |
| From: Tejun Heo <tj@kernel.org> |
| |
| 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> |
| |
| --- |
| drivers/scsi/libsas/sas_ata.c | 4 ++++ |
| drivers/scsi/libsas/sas_scsi_host.c | 4 ++++ |
| 2 files changed, 8 insertions(+) |
| |
| --- 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 do |
| void sas_ata_task_abort(struct sas_task *task) |
| { |
| struct ata_queued_cmd *qc = task->uldd_task; |
| + struct request_queue *q = qc->scsicmd->device->request_queue; |
| struct completion *waiting; |
| + unsigned long flags; |
| |
| /* Bounce SCSI-initiated commands to the SCSI EH */ |
| if (qc->scsicmd) { |
| + spin_lock_irqsave(q->queue_lock, flags); |
| blk_abort_request(qc->scsicmd->request); |
| + spin_unlock_irqrestore(q->queue_lock, flags); |
| scsi_schedule_eh(qc->scsicmd->device->host); |
| return; |
| } |
| --- 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 *ta |
| void sas_task_abort(struct sas_task *task) |
| { |
| struct scsi_cmnd *sc = task->uldd_task; |
| + struct request_queue *q = sc->device->request_queue; |
| + unsigned long flags; |
| |
| /* Escape for libsas internal commands */ |
| if (!sc) { |
| @@ -1043,7 +1045,9 @@ void sas_task_abort(struct sas_task *tas |
| return; |
| } |
| |
| + spin_lock_irqsave(q->queue_lock, flags); |
| blk_abort_request(sc->request); |
| + spin_unlock_irqrestore(q->queue_lock, flags); |
| scsi_schedule_eh(sc->device->host); |
| } |
| |