Commit 7a49740a authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] as-iosched barrier fix

From: Jens Axboe <axboe@suse.de>

AS does not correctly account requests inserted with INSERT_FRONT or
INSERT_BACK, barriers for example.  In other elevators, requeued requests also
go through the insert path, but AS has its own requeue handler which means the
code has never been tested.

Also, make inserting a barrier with INSERT_SORT imply INSERT_BACK, which is
the logical behaviour.  Previously such insertions weren't rigorously defined.
parent e829d2e4
...@@ -1216,13 +1216,12 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) ...@@ -1216,13 +1216,12 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
} }
as_remove_queued_request(ad->q, rq); as_remove_queued_request(ad->q, rq);
WARN_ON(arq->state != AS_RQ_QUEUED);
list_add(&rq->queuelist, insert); list_add(&rq->queuelist, insert);
arq->state = AS_RQ_DISPATCHED;
if (arq->io_context && arq->io_context->aic) if (arq->io_context && arq->io_context->aic)
atomic_inc(&arq->io_context->aic->nr_dispatched); atomic_inc(&arq->io_context->aic->nr_dispatched);
WARN_ON(arq->state != AS_RQ_QUEUED);
arq->state = AS_RQ_DISPATCHED;
ad->nr_dispatched++; ad->nr_dispatched++;
} }
...@@ -1492,6 +1491,21 @@ static void as_requeue_request(request_queue_t *q, struct request *rq) ...@@ -1492,6 +1491,21 @@ static void as_requeue_request(request_queue_t *q, struct request *rq)
as_antic_stop(ad); as_antic_stop(ad);
} }
/*
* Account a request that is inserted directly onto the dispatch queue.
* arq->io_context->aic->nr_dispatched should not need to be incremented
* because only new requests should come through here: requeues go through
* our explicit requeue handler.
*/
static void as_account_queued_request(struct as_data *ad, struct request *rq)
{
if (blk_fs_request(rq)) {
struct as_rq *arq = RQ_DATA(rq);
arq->state = AS_RQ_DISPATCHED;
ad->nr_dispatched++;
}
}
static void static void
as_insert_request(request_queue_t *q, struct request *rq, int where) as_insert_request(request_queue_t *q, struct request *rq, int where)
{ {
...@@ -1522,10 +1536,12 @@ as_insert_request(request_queue_t *q, struct request *rq, int where) ...@@ -1522,10 +1536,12 @@ as_insert_request(request_queue_t *q, struct request *rq, int where)
as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
list_add_tail(&rq->queuelist, ad->dispatch); list_add_tail(&rq->queuelist, ad->dispatch);
as_account_queued_request(ad, rq);
as_antic_stop(ad); as_antic_stop(ad);
break; break;
case ELEVATOR_INSERT_FRONT: case ELEVATOR_INSERT_FRONT:
list_add(&rq->queuelist, ad->dispatch); list_add(&rq->queuelist, ad->dispatch);
as_account_queued_request(ad, rq);
as_antic_stop(ad); as_antic_stop(ad);
break; break;
case ELEVATOR_INSERT_SORT: case ELEVATOR_INSERT_SORT:
......
...@@ -169,6 +169,13 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) ...@@ -169,6 +169,13 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
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)
{ {
/*
* barriers implicitly indicate back insertion
*/
if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) &&
where == ELEVATOR_INSERT_SORT)
where = ELEVATOR_INSERT_BACK;
if (plug) if (plug)
blk_plug_device(q); blk_plug_device(q);
......
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