]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
SCSI: fix locking around blk_abort_request()
authorTejun Heo <tj@kernel.org>
Thu, 15 Apr 2010 00:00:08 +0000 (09:00 +0900)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 12 May 2010 21:57:16 +0000 (14:57 -0700)
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
drivers/scsi/libsas/sas_scsi_host.c

index e15501170698a19957d22f92c6fbc2e3e89ac0c6..816ab97eb16da1c3269999e72912303dbe2f2c99 100644 (file)
@@ -394,11 +394,15 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
 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;
        }
index 1c558d3bce18c4817623078944e86557eb3adb9f..39fb9aa93fe51175e4a18ae3c4b47cc4e3d2d3ce 100644 (file)
@@ -1025,6 +1025,8 @@ int __sas_task_abort(struct sas_task *task)
 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) {
@@ -1039,7 +1041,9 @@ void sas_task_abort(struct sas_task *task)
                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);
 }