
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.



---

 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);
 

_
