diff options
author | Tejun Heo <tj@kernel.org> | 2010-04-14 19:57:37 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2010-04-22 21:47:52 -0400 |
commit | fa41efdae7de61191a7bda3a00e88ef69afb5bb9 (patch) | |
tree | 6bd4a8d48bbf0e8be01304e0914a575916e2b9fc /drivers/ata/libata-eh.c | |
parent | c81eddb0e3728661d1585fbc564449c94165cc36 (diff) |
libata: fix locking around blk_abort_request()
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>
Cc: stable@kernel.org
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 9f6cfac0f2cc..9e18cc9be0d3 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -879,6 +879,8 @@ static void ata_eh_set_pending(struct ata_port *ap, int fastdrain) | |||
879 | void ata_qc_schedule_eh(struct ata_queued_cmd *qc) | 879 | void ata_qc_schedule_eh(struct ata_queued_cmd *qc) |
880 | { | 880 | { |
881 | struct ata_port *ap = qc->ap; | 881 | struct ata_port *ap = qc->ap; |
882 | struct request_queue *q = qc->scsicmd->device->request_queue; | ||
883 | unsigned long flags; | ||
882 | 884 | ||
883 | WARN_ON(!ap->ops->error_handler); | 885 | WARN_ON(!ap->ops->error_handler); |
884 | 886 | ||
@@ -890,7 +892,9 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc) | |||
890 | * Note that ATA_QCFLAG_FAILED is unconditionally set after | 892 | * Note that ATA_QCFLAG_FAILED is unconditionally set after |
891 | * this function completes. | 893 | * this function completes. |
892 | */ | 894 | */ |
895 | spin_lock_irqsave(q->queue_lock, flags); | ||
893 | blk_abort_request(qc->scsicmd->request); | 896 | blk_abort_request(qc->scsicmd->request); |
897 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
894 | } | 898 | } |
895 | 899 | ||
896 | /** | 900 | /** |