diff options
author | Tejun Heo <htejun@gmail.com> | 2006-01-12 15:39:26 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-12 09:05:39 -0800 |
commit | 1bc691d357c646700b9523d2aeca02847d3fb3f4 (patch) | |
tree | 430e13982f894c44e4a33dee188b3c718ec989ed /block/elevator.c | |
parent | 593195f9b2309693f27b402f34573f7920b82c3e (diff) | |
download | lwn-1bc691d357c646700b9523d2aeca02847d3fb3f4.tar.gz lwn-1bc691d357c646700b9523d2aeca02847d3fb3f4.zip |
[PATCH] fix queue stalling while barrier sequencing
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>
Diffstat (limited to 'block/elevator.c')
-rw-r--r-- | block/elevator.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/block/elevator.c b/block/elevator.c index 99a4d7b2f8ad..1d0759178e4b 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -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); } } |