]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
libata: fix locking around blk_abort_request()
authorTejun Heo <tj@kernel.org>
Wed, 14 Apr 2010 23:57:37 +0000 (08:57 +0900)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 12 May 2010 21:56:59 +0000 (14:56 -0700)
commit fa41efdae7de61191a7bda3a00e88ef69afb5bb9 upstream.

blk_abort_request() expectes 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: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/ata/libata-eh.c

index 7d8d3c3b4c80b09dbf5f9d7742094cffd2f212c6..c85992ba8dff3d5bf9c1d085bac20b554cbf8b42 100644 (file)
@@ -870,6 +870,8 @@ static void ata_eh_set_pending(struct ata_port *ap, int fastdrain)
 void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
+       struct request_queue *q = qc->scsicmd->device->request_queue;
+       unsigned long flags;
 
        WARN_ON(!ap->ops->error_handler);
 
@@ -881,7 +883,9 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
         * Note that ATA_QCFLAG_FAILED is unconditionally set after
         * this function completes.
         */
+       spin_lock_irqsave(q->queue_lock, flags);
        blk_abort_request(qc->scsicmd->request);
+       spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 /**