Commit 15853af9 authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

[BLOCK] Implement elv_drain_elevator for improved switch error detection

This patch adds request_queue->nr_sorted which keeps the number of
requests in the iosched and implement elv_drain_elevator which
performs forced dispatching.  elv_drain_elevator checks whether
iosched actually dispatches all requests it has and prints error
message if it doesn't.  As buggy forced dispatching can result in
wrong barrier operations, I think this extra check is worthwhile.
Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJens Axboe <axboe@suse.de>
parent 1b5ed5e1
...@@ -226,6 +226,7 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq) ...@@ -226,6 +226,7 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
if (q->last_merge == rq) if (q->last_merge == rq)
q->last_merge = NULL; q->last_merge = NULL;
q->nr_sorted--;
boundary = q->end_sector; boundary = q->end_sector;
...@@ -284,6 +285,7 @@ void elv_merge_requests(request_queue_t *q, struct request *rq, ...@@ -284,6 +285,7 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
if (e->ops->elevator_merge_req_fn) if (e->ops->elevator_merge_req_fn)
e->ops->elevator_merge_req_fn(q, rq, next); e->ops->elevator_merge_req_fn(q, rq, next);
q->nr_sorted--;
q->last_merge = rq; q->last_merge = rq;
} }
...@@ -315,6 +317,20 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) ...@@ -315,6 +317,20 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
} }
static void elv_drain_elevator(request_queue_t *q)
{
static int printed;
while (q->elevator->ops->elevator_dispatch_fn(q, 1))
;
if (q->nr_sorted == 0)
return;
if (printed++ < 10) {
printk(KERN_ERR "%s: forced dispatching is broken "
"(nr_sorted=%u), please report this\n",
q->elevator->elevator_type->elevator_name, q->nr_sorted);
}
}
void __elv_add_request(request_queue_t *q, struct request *rq, int where, void __elv_add_request(request_queue_t *q, struct request *rq, int where,
int plug) int plug)
{ {
...@@ -349,9 +365,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, ...@@ -349,9 +365,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
case ELEVATOR_INSERT_BACK: case ELEVATOR_INSERT_BACK:
rq->flags |= REQ_SOFTBARRIER; rq->flags |= REQ_SOFTBARRIER;
elv_drain_elevator(q);
while (q->elevator->ops->elevator_dispatch_fn(q, 1))
;
list_add_tail(&rq->queuelist, &q->queue_head); list_add_tail(&rq->queuelist, &q->queue_head);
/* /*
* We kick the queue here for the following reasons. * We kick the queue here for the following reasons.
...@@ -370,6 +384,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, ...@@ -370,6 +384,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
case ELEVATOR_INSERT_SORT: case ELEVATOR_INSERT_SORT:
BUG_ON(!blk_fs_request(rq)); BUG_ON(!blk_fs_request(rq));
rq->flags |= REQ_SORTED; rq->flags |= REQ_SORTED;
q->nr_sorted++;
if (q->last_merge == NULL && rq_mergeable(rq)) if (q->last_merge == NULL && rq_mergeable(rq))
q->last_merge = rq; q->last_merge = rq;
/* /*
...@@ -692,8 +707,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) ...@@ -692,8 +707,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
while (q->elevator->ops->elevator_dispatch_fn(q, 1)) elv_drain_elevator(q);
;
while (q->rq.elvpriv) { while (q->rq.elvpriv) {
blk_remove_plug(q); blk_remove_plug(q);
...@@ -701,6 +715,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) ...@@ -701,6 +715,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
msleep(10); msleep(10);
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
elv_drain_elevator(q);
} }
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
......
...@@ -406,6 +406,7 @@ struct request_queue ...@@ -406,6 +406,7 @@ struct request_queue
atomic_t refcnt; atomic_t refcnt;
unsigned int nr_sorted;
unsigned int in_flight; unsigned int in_flight;
/* /*
...@@ -631,6 +632,7 @@ static inline void elv_dispatch_add_tail(struct request_queue *q, ...@@ -631,6 +632,7 @@ static inline void elv_dispatch_add_tail(struct request_queue *q,
{ {
if (q->last_merge == rq) if (q->last_merge == rq)
q->last_merge = NULL; q->last_merge = NULL;
q->nr_sorted--;
q->end_sector = rq_end_sector(rq); q->end_sector = rq_end_sector(rq);
q->boundary_rq = rq; q->boundary_rq = rq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment