CFQ: add think time check for service tree
[linux-2.6.git] / block / blk-flush.c
index a867e3f..bb21e4c 100644 (file)
@@ -194,7 +194,6 @@ static void flush_end_io(struct request *flush_rq, int error)
 {
        struct request_queue *q = flush_rq->q;
        struct list_head *running = &q->flush_queue[q->flush_running_idx];
-       bool was_empty = elv_queue_empty(q);
        bool queued = false;
        struct request *rq, *n;
 
@@ -212,9 +211,20 @@ static void flush_end_io(struct request *flush_rq, int error)
                queued |= blk_flush_complete_seq(rq, seq, error);
        }
 
-       /* after populating an empty queue, kick it to avoid stall */
-       if (queued && was_empty)
-               __blk_run_queue(q);
+       /*
+        * Kick the queue to avoid stall for two cases:
+        * 1. Moving a request silently to empty queue_head may stall the
+        * queue.
+        * 2. When flush request is running in non-queueable queue, the
+        * queue is hold. Restart the queue after flush request is finished
+        * to avoid stall.
+        * This function is called from request completion path and calling
+        * directly into request_fn may confuse the driver.  Always use
+        * kblockd.
+        */
+       if (queued || q->flush_queue_delayed)
+               blk_run_queue_async(q);
+       q->flush_queue_delayed = 0;
 }
 
 /**
@@ -257,25 +267,27 @@ static bool blk_kick_flush(struct request_queue *q)
        q->flush_rq.end_io = flush_end_io;
 
        q->flush_pending_idx ^= 1;
-       elv_insert(q, &q->flush_rq, ELEVATOR_INSERT_FRONT);
+       list_add_tail(&q->flush_rq.queuelist, &q->queue_head);
        return true;
 }
 
 static void flush_data_end_io(struct request *rq, int error)
 {
        struct request_queue *q = rq->q;
-       bool was_empty = elv_queue_empty(q);
 
-       /* after populating an empty queue, kick it to avoid stall */
-       if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error) && was_empty)
-               __blk_run_queue(q);
+       /*
+        * After populating an empty queue, kick it to avoid stall.  Read
+        * the comment in flush_end_io().
+        */
+       if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error))
+               blk_run_queue_async(q);
 }
 
 /**
  * blk_insert_flush - insert a new FLUSH/FUA request
  * @rq: request to insert
  *
- * To be called from elv_insert() for %ELEVATOR_INSERT_FLUSH insertions.
+ * To be called from __elv_add_request() for %ELEVATOR_INSERT_FLUSH insertions.
  * @rq is being submitted.  Analyze what needs to be done and put it on the
  * right queue.
  *
@@ -306,7 +318,7 @@ void blk_insert_flush(struct request *rq)
         */
        if ((policy & REQ_FSEQ_DATA) &&
            !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
-               list_add(&rq->queuelist, &q->queue_head);
+               list_add_tail(&rq->queuelist, &q->queue_head);
                return;
        }