[PATCH] fix queue stalling while barrier sequencing
authorTejun Heo <htejun@gmail.com>
Thu, 12 Jan 2006 14:39:26 +0000 (15:39 +0100)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 12 Jan 2006 17:05:39 +0000 (09:05 -0800)
If ordered tag isn't supported, request ordering for barrier
sequencing is performed by queue draining, which basically hangs the
request queue until elv_completed_request() reports completion of all
previous fs requests.

The condition check in elv_completed_request() was only performed for
fs requests.  If a special request is queued between the last
to-be-drained request and the barrier sequence, draining is never
completed and the queue is stalled forever.

This patch moves the end-of-draining condition check such that it's
performed for all requests.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jens Axboe <axboe@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
block/elevator.c

index 99a4d7b2f8ad335079ae1eebeab71136f20acc35..1d0759178e4b49710c6cb90c538fc6d0c897e126 100644 (file)
@@ -610,23 +610,23 @@ void elv_completed_request(request_queue_t *q, struct request *rq)
         * request is released from the driver, io must be done
         */
        if (blk_account_rq(rq)) {
-               struct request *first_rq = list_entry_rq(q->queue_head.next);
-
                q->in_flight--;
+               if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
+                       e->ops->elevator_completed_req_fn(q, rq);
+       }
 
-               /*
-                * Check if the queue is waiting for fs requests to be
-                * drained for flush sequence.
-                */
-               if (q->ordseq && q->in_flight == 0 &&
+       /*
+        * Check if the queue is waiting for fs requests to be
+        * drained for flush sequence.
+        */
+       if (unlikely(q->ordseq)) {
+               struct request *first_rq = list_entry_rq(q->queue_head.next);
+               if (q->in_flight == 0 &&
                    blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
                    blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) {
                        blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
                        q->request_fn(q);
                }
-
-               if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
-                       e->ops->elevator_completed_req_fn(q, rq);
        }
 }