From: Jens Axboe 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. --- 25-akpm/drivers/block/as-iosched.c | 24 ++++++++++++++++++++---- 25-akpm/drivers/block/elevator.c | 7 +++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff -puN drivers/block/as-iosched.c~as-iosched-cleanups drivers/block/as-iosched.c --- 25/drivers/block/as-iosched.c~as-iosched-cleanups 2004-05-07 00:17:52.598658272 -0700 +++ 25-akpm/drivers/block/as-iosched.c 2004-05-07 00:17:52.604657360 -0700 @@ -1216,13 +1216,12 @@ static void as_move_to_dispatch(struct a } as_remove_queued_request(ad->q, rq); + WARN_ON(arq->state != AS_RQ_QUEUED); + list_add(&rq->queuelist, insert); + arq->state = AS_RQ_DISPATCHED; if (arq->io_context && arq->io_context->aic) atomic_inc(&arq->io_context->aic->nr_dispatched); - - WARN_ON(arq->state != AS_RQ_QUEUED); - arq->state = AS_RQ_DISPATCHED; - ad->nr_dispatched++; } @@ -1492,6 +1491,21 @@ static void as_requeue_request(request_q 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 as_insert_request(request_queue_t *q, struct request *rq, int where) { @@ -1522,10 +1536,12 @@ as_insert_request(request_queue_t *q, st as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); list_add_tail(&rq->queuelist, ad->dispatch); + as_account_queued_request(ad, rq); as_antic_stop(ad); break; case ELEVATOR_INSERT_FRONT: list_add(&rq->queuelist, ad->dispatch); + as_account_queued_request(ad, rq); as_antic_stop(ad); break; case ELEVATOR_INSERT_SORT: diff -puN drivers/block/elevator.c~as-iosched-cleanups drivers/block/elevator.c --- 25/drivers/block/elevator.c~as-iosched-cleanups 2004-05-07 00:17:52.600657968 -0700 +++ 25-akpm/drivers/block/elevator.c 2004-05-07 00:17:52.604657360 -0700 @@ -169,6 +169,13 @@ void elv_requeue_request(request_queue_t void __elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { + /* + * barriers implicitly indicate back insertion + */ + if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) && + where == ELEVATOR_INSERT_SORT) + where = ELEVATOR_INSERT_BACK; + if (plug) blk_plug_device(q); _