Patch from Nick Piggin drivers/block/as-iosched.c | 33 ++++++++++++++++++++++++--------- 1 files changed, 24 insertions(+), 9 deletions(-) diff -puN drivers/block/as-iosched.c~as-as_remove_request-simplification drivers/block/as-iosched.c --- 25/drivers/block/as-iosched.c~as-as_remove_request-simplification 2003-03-16 21:28:28.000000000 -0800 +++ 25-akpm/drivers/block/as-iosched.c 2003-03-16 21:28:28.000000000 -0800 @@ -910,7 +910,6 @@ static void as_complete_arq(struct as_da as_antic_waitnext(ad); } } - put_as_io_context(&arq->as_io_context); } /* @@ -956,14 +955,12 @@ static void as_remove_queued_request(req } /* - * as_remove_request is called when a driver has completed the request - * (or it has caused an error), and is finished with it. It assumes - * the request is on the dispatch queue. + * as_remove_dispatched_request is called to remove a request which has gone + * to the dispatch list. */ -static void as_remove_request(request_queue_t *q, struct request *rq) +static void as_remove_dispatched_request(request_queue_t *q, struct request *rq) { struct as_rq *arq = RQ_DATA(rq); - struct as_data *ad = q->elevator.elevator_data; if (q->last_merge == &rq->queuelist) q->last_merge = NULL; @@ -971,14 +968,32 @@ static void as_remove_request(request_qu list_del_init(&rq->queuelist); if (arq) { - list_del_init(&arq->fifo); - as_del_arq_hash(arq); - as_del_arq_rb(ad, arq); + BUG_ON(arq->state != AS_RQ_DISPATCHED); + BUG_ON(ON_RB(&arq->rb_node)); if (arq->as_io_context) { WARN_ON(!atomic_read(&arq->as_io_context->nr_dispatched)); atomic_dec(&arq->as_io_context->nr_dispatched); } + } +} +/* + * as_remove_request is called when a driver has finished with a request. + * This should be only called for dispatched requests, but for some reason + * a POWER4 box running hwscan it does not. + */ +static void as_remove_request(request_queue_t *q, struct request *rq) +{ + struct as_data *ad = q->elevator.elevator_data; + struct as_rq *arq = RQ_DATA(rq); + + if (arq) { + if (ON_RB(&arq->rb_node)) + as_remove_queued_request(q, rq); + else + as_remove_dispatched_request(q, rq); + as_complete_arq(ad, arq); + put_as_io_context(&arq->as_io_context); } } _