From: Stephen Rothwell Date: Wed, 21 Dec 2011 02:49:51 +0000 (+1100) Subject: Merge remote-tracking branch 'block/for-next' X-Git-Tag: next-20111221~48 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=b9a55e4a438101f162eb6773aa020ef98c646177;p=karo-tx-linux.git Merge remote-tracking branch 'block/for-next' --- b9a55e4a438101f162eb6773aa020ef98c646177 diff --cc block/blk-core.c index 15de223c7f93,1b4fd93af2c0..e6c05a97ee2b --- a/block/blk-core.c +++ b/block/blk-core.c @@@ -366,19 -369,23 +369,30 @@@ void blk_drain_queue(struct request_que if (drain_all) blk_throtl_drain(q); - __blk_run_queue(q); + /* + * This function might be called on a queue which failed + * driver init after queue creation. Some drivers + * (e.g. fd) get unhappy in such cases. Kick queue iff + * dispatch queue has something on it. + */ + if (!list_empty(&q->queue_head)) + __blk_run_queue(q); - if (drain_all) - nr_rqs = q->rq.count[0] + q->rq.count[1]; - else - nr_rqs = q->rq.elvpriv; + drain |= q->rq.elvpriv; + + /* + * Unfortunately, requests are queued at and tracked from + * multiple places and there's no single counter which can + * be drained. Check all the queues and counters. + */ + if (drain_all) { + drain |= !list_empty(&q->queue_head); + for (i = 0; i < 2; i++) { + drain |= q->rq.count[i]; + drain |= q->in_flight[i]; + drain |= !list_empty(&q->flush_queue[i]); + } + } spin_unlock_irq(q->queue_lock);