From: Nick Piggin Seeing as the previous unfair behaviour of the request allocator has gone, AS is up the creek. This patch implements a hint (Jens, I commandeered elv_may_queue) so that AS can tell the request allocator to allocate a request even if there are none left (the accounting is quite flexible and easily handles overallocations). elv_may_queue semantics have changed from "the elevator does _not_ want another request allocated" to "the elevator _insists_ that another request is allocated". I couldn't see any harm ;) Now in practice, AS will only allow _1_ request over the limit, because as soon as the request is sent to AS, it stops anticipating. Anyway, with this and the previous patch, 64 dd's in parallel get around about disk bandwidth (22MB/s). With nr_requests == 4, I still see around 15MB/s. Quite impressive. drivers/block/as-iosched.c | 15 +++++++++++++++ drivers/block/elevator.c | 2 +- drivers/block/ll_rw_blk.c | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff -puN drivers/block/as-iosched.c~blk-as-hint drivers/block/as-iosched.c --- 25/drivers/block/as-iosched.c~blk-as-hint 2003-05-31 19:56:35.000000000 -0700 +++ 25-akpm/drivers/block/as-iosched.c 2003-05-31 19:56:35.000000000 -0700 @@ -1565,6 +1565,20 @@ static int as_set_request(request_queue_ return 1; } +static int as_may_queue(request_queue_t *q, int rw) +{ + struct as_data *ad = q->elevator.elevator_data; + struct as_io_context *aic; + if (ad->antic_status == ANTIC_WAIT_REQ || + ad->antic_status == ANTIC_WAIT_NEXT) { + aic = get_as_io_context(); + if (ad->as_io_context == aic) + return 1; + } + + return 0; +} + static void as_exit(request_queue_t *q, elevator_t *e) { struct as_data *ad = e->elevator_data; @@ -1792,6 +1806,7 @@ elevator_t iosched_as = { .elevator_latter_req_fn = as_latter_request, .elevator_set_req_fn = as_set_request, .elevator_put_req_fn = as_put_request, + .elevator_may_queue_fn = as_may_queue, .elevator_init_fn = as_init, .elevator_exit_fn = as_exit, diff -puN drivers/block/elevator.c~blk-as-hint drivers/block/elevator.c --- 25/drivers/block/elevator.c~blk-as-hint 2003-05-31 19:56:35.000000000 -0700 +++ 25-akpm/drivers/block/elevator.c 2003-05-31 19:56:35.000000000 -0700 @@ -368,7 +368,7 @@ int elv_may_queue(request_queue_t *q, in if (e->elevator_may_queue_fn) return e->elevator_may_queue_fn(q, rw); - return 1; + return 0; } void elv_completed_request(request_queue_t *q, struct request *rq) diff -puN drivers/block/ll_rw_blk.c~blk-as-hint drivers/block/ll_rw_blk.c --- 25/drivers/block/ll_rw_blk.c~blk-as-hint 2003-05-31 19:56:35.000000000 -0700 +++ 25-akpm/drivers/block/ll_rw_blk.c 2003-05-31 19:56:35.000000000 -0700 @@ -1351,7 +1351,7 @@ static struct request *get_request(reque if (rl->count[rw] == q->nr_requests) blk_set_queue_full(q, rw); - if (blk_queue_full(q, rw) || !elv_may_queue(q, rw)) { + if (blk_queue_full(q, rw) && !elv_may_queue(q, rw)) { spin_unlock_irq(q->queue_lock); goto out; } _