Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)

	if (q->last_merge == rq)
		q->last_merge = NULL;
	q->nr_sorted--;

	boundary = q->end_sector;

@@ -284,6 +285,7 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,

	if (e->ops->elevator_merge_req_fn)
		e->ops->elevator_merge_req_fn(q, rq, next);
	q->nr_sorted--;

	q->last_merge = 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);
}

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,
		       int plug)
{
@@ -349,9 +365,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,

	case ELEVATOR_INSERT_BACK:
		rq->flags |= REQ_SOFTBARRIER;

		while (q->elevator->ops->elevator_dispatch_fn(q, 1))
			;
		elv_drain_elevator(q);
		list_add_tail(&rq->queuelist, &q->queue_head);
		/*
		 * 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,
	case ELEVATOR_INSERT_SORT:
		BUG_ON(!blk_fs_request(rq));
		rq->flags |= REQ_SORTED;
		q->nr_sorted++;
		if (q->last_merge == NULL && rq_mergeable(rq))
			q->last_merge = rq;
		/*
@@ -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);

	while (q->elevator->ops->elevator_dispatch_fn(q, 1))
		;
	elv_drain_elevator(q);

	while (q->rq.elvpriv) {
		blk_remove_plug(q);
@@ -701,6 +715,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
		spin_unlock_irq(q->queue_lock);
		msleep(10);
		spin_lock_irq(q->queue_lock);
		elv_drain_elevator(q);
	}

	spin_unlock_irq(q->queue_lock);
+2 −0
Original line number Diff line number Diff line
@@ -406,6 +406,7 @@ struct request_queue

	atomic_t		refcnt;

	unsigned int		nr_sorted;
	unsigned int		in_flight;

	/*
@@ -631,6 +632,7 @@ static inline void elv_dispatch_add_tail(struct request_queue *q,
{
	if (q->last_merge == rq)
		q->last_merge = NULL;
	q->nr_sorted--;

	q->end_sector = rq_end_sector(rq);
	q->boundary_rq = rq;