|
@@ -358,7 +358,8 @@ EXPORT_SYMBOL(blk_put_queue);
|
|
void blk_drain_queue(struct request_queue *q, bool drain_all)
|
|
void blk_drain_queue(struct request_queue *q, bool drain_all)
|
|
{
|
|
{
|
|
while (true) {
|
|
while (true) {
|
|
- int nr_rqs;
|
|
|
|
|
|
+ bool drain = false;
|
|
|
|
+ int i;
|
|
|
|
|
|
spin_lock_irq(q->queue_lock);
|
|
spin_lock_irq(q->queue_lock);
|
|
|
|
|
|
@@ -368,14 +369,25 @@ void blk_drain_queue(struct request_queue *q, bool drain_all)
|
|
|
|
|
|
__blk_run_queue(q);
|
|
__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);
|
|
spin_unlock_irq(q->queue_lock);
|
|
|
|
|
|
- if (!nr_rqs)
|
|
|
|
|
|
+ if (!drain)
|
|
break;
|
|
break;
|
|
msleep(10);
|
|
msleep(10);
|
|
}
|
|
}
|