diff --git a/[refs] b/[refs] index a9e4571b97a8..8cfb7263d69a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6d407cfaf5a56b3030b9e55d0f542601e173c5d2 +refs/heads/master: 458f27a9823a0841acb4ca59e0e7f33e181f85e2 diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index 3c923a7aeb56..ce7fbf8d85a6 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -361,9 +361,10 @@ EXPORT_SYMBOL(blk_put_queue); */ void blk_drain_queue(struct request_queue *q, bool drain_all) { + int i; + while (true) { bool drain = false; - int i; spin_lock_irq(q->queue_lock); @@ -408,6 +409,18 @@ void blk_drain_queue(struct request_queue *q, bool drain_all) break; msleep(10); } + + /* + * With queue marked dead, any woken up waiter will fail the + * allocation path, so the wakeup chaining is lost and we're + * left with hung waiters. We need to wake up those waiters. + */ + if (q->request_fn) { + spin_lock_irq(q->queue_lock); + for (i = 0; i < ARRAY_SIZE(q->rq.wait); i++) + wake_up_all(&q->rq.wait[i]); + spin_unlock_irq(q->queue_lock); + } } /**