block: fix deadlock in blk_abort_queue() for drivers that readd to timeout list
blk_abort_queue() iterates the timeout list and aborts each request on the list, but if the driver error handling readds a request to the timeout list during this processing, we could be looping forever. Fix this by splicing current entries to a local list and run over that list instead. Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
This commit is contained in:
parent
41b8c853a4
commit
be987fdb55
|
@ -209,12 +209,19 @@ void blk_abort_queue(struct request_queue *q)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct request *rq, *tmp;
|
struct request *rq, *tmp;
|
||||||
|
LIST_HEAD(list);
|
||||||
|
|
||||||
spin_lock_irqsave(q->queue_lock, flags);
|
spin_lock_irqsave(q->queue_lock, flags);
|
||||||
|
|
||||||
elv_abort_queue(q);
|
elv_abort_queue(q);
|
||||||
|
|
||||||
list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list)
|
/*
|
||||||
|
* Splice entries to local list, to avoid deadlocking if entries
|
||||||
|
* get readded to the timeout list by error handling
|
||||||
|
*/
|
||||||
|
list_splice_init(&q->timeout_list, &list);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(rq, tmp, &list, timeout_list)
|
||||||
blk_abort_request(rq);
|
blk_abort_request(rq);
|
||||||
|
|
||||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
spin_unlock_irqrestore(q->queue_lock, flags);
|
||||||
|
|
Loading…
Reference in New Issue