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>
This commit is contained in:
parent
c81eddb0e3
commit
fa41efdae7
1 changed files with 4 additions and 0 deletions
|
@ -879,6 +879,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);
|
||||
|
||||
|
@ -890,7 +892,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue