| From fa41efdae7de61191a7bda3a00e88ef69afb5bb9 Mon Sep 17 00:00:00 2001 |
| From: Tejun Heo <tj@kernel.org> |
| Date: Thu, 15 Apr 2010 08:57:37 +0900 |
| Subject: libata: fix locking around blk_abort_request() |
| |
| From: Tejun Heo <tj@kernel.org> |
| |
| 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 | 4 ++++ |
| 1 file changed, 4 insertions(+) |
| |
| --- a/drivers/ata/libata-eh.c |
| +++ b/drivers/ata/libata-eh.c |
| @@ -879,6 +879,8 @@ static void ata_eh_set_pending(struct at |
| 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); |
| |
| @@ -890,7 +892,9 @@ void ata_qc_schedule_eh(struct ata_queue |
| * 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); |
| } |
| |
| /** |