Patch from Nick Piggin <piggin@cyberone.com.au>



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

_