aboutsummaryrefslogtreecommitdiffstats
path: root/block/elevator.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-11-27 23:32:05 -0500
committerJens Axboe <jens.axboe@oracle.com>2008-12-29 02:28:45 -0500
commit8f11b3e99a1136fcbb67316c3260f085299c0bff (patch)
treebb9b12fe23aceac19e24f674786612d0fcad2142 /block/elevator.c
parentf671620e7d895af221bdfeda751d54fa55ed9546 (diff)
block: make barrier completion more robust
Barrier completion had the following assumptions. * start_ordered() couldn't finish the whole sequence properly. If all actions are to be skipped, q->ordseq is set correctly but the actual completion was never triggered thus hanging the barrier request. * Drain completion in elv_complete_request() assumed that there's always at least one request in the queue when drain completes. Both assumptions are true but these assumptions need to be removed to improve empty barrier implementation. This patch makes the following changes. * Make start_ordered() use blk_ordered_complete_seq() to mark skipped steps complete and notify __elv_next_request() that it should fetch the next request if the whole barrier has completed inside start_ordered(). * Make drain completion path in elv_complete_request() check whether the queue is empty. Empty queue also indicates drain completion. * While at it, convert 0/1 return from blk_do_ordered() to false/true. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/elevator.c')
-rw-r--r--block/elevator.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/block/elevator.c b/block/elevator.c
index 86836dd179c0..261ffaaf47bd 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -944,10 +944,14 @@ void elv_completed_request(struct request_queue *q, struct request *rq)
944 * drained for flush sequence. 944 * drained for flush sequence.
945 */ 945 */
946 if (unlikely(q->ordseq)) { 946 if (unlikely(q->ordseq)) {
947 struct request *first_rq = list_entry_rq(q->queue_head.next); 947 struct request *next = NULL;
948 if (q->in_flight == 0 && 948
949 if (!list_empty(&q->queue_head))
950 next = list_entry_rq(q->queue_head.next);
951
952 if (!q->in_flight &&
949 blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN && 953 blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
950 blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) { 954 (!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) {
951 blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0); 955 blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
952 blk_start_queueing(q); 956 blk_start_queueing(q);
953 } 957 }