<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Nick Piggin &lt;piggin@cyberone.com.au&gt;

I have tested this on my disks and cdroms, but they don't represent
what all drivers might do. I have asked Jarkko Lehti with his dvd writing
problem to try it...



 drivers/block/as-iosched.c |  101 +++++++++++++++++++++++++++++++--------------
 1 files changed, 70 insertions(+), 31 deletions(-)

diff -puN drivers/block/as-iosched.c~as-request-poisoning drivers/block/as-iosched.c
--- 25/drivers/block/as-iosched.c~as-request-poisoning	2003-11-09 16:39:52.000000000 -0800
+++ 25-akpm/drivers/block/as-iosched.c	2003-11-09 16:39:52.000000000 -0800
@@ -136,6 +136,10 @@ enum arq_state {
 				   scheduler */
 	AS_RQ_DISPATCHED,	/* On the dispatch list. It belongs to the
 				   driver now */
+	AS_RQ_PRESCHED,		/* Debug poisoning for requests being used */
+	AS_RQ_REMOVED,
+	AS_RQ_MERGED,
+	AS_RQ_POSTSCHED,	/* when they shouldn't be */
 };
 
 struct as_rq {
@@ -893,12 +897,22 @@ static void as_completed_request(request
 {
 	struct as_data *ad = q-&gt;elevator.elevator_data;
 	struct as_rq *arq = RQ_DATA(rq);
-	struct as_io_context *aic;
 
 	WARN_ON(!list_empty(&amp;rq-&gt;queuelist));
 
-	if (unlikely(arq-&gt;state != AS_RQ_DISPATCHED))
-		return;
+	if (arq-&gt;state == AS_RQ_PRESCHED) {
+		WARN_ON(arq-&gt;io_context);
+		goto out;
+	}
+
+	if (arq-&gt;state == AS_RQ_MERGED)
+		goto out_ioc;
+
+	if (arq-&gt;state != AS_RQ_REMOVED) {
+		printk("arq-&gt;state %d\n", arq-&gt;state);
+		WARN_ON(1);
+		goto out;
+	}
 
 	if (!blk_fs_request(rq))
 		return;
@@ -925,10 +939,7 @@ static void as_completed_request(request
 		ad-&gt;new_batch = 0;
 	}
 
-	if (!arq-&gt;io_context)
-		return;
-
-	if (ad-&gt;io_context == arq-&gt;io_context) {
+	if (ad-&gt;io_context == arq-&gt;io_context &amp;&amp; ad-&gt;io_context) {
 		ad-&gt;antic_start = jiffies;
 		ad-&gt;ioc_finished = 1;
 		if (ad-&gt;antic_status == ANTIC_WAIT_REQ) {
@@ -940,18 +951,23 @@ static void as_completed_request(request
 		}
 	}
 
-	aic = arq-&gt;io_context-&gt;aic;
-	if (!aic)
-		return;
+out_ioc:
+	if (!arq-&gt;io_context)
+		goto out;
 
-	spin_lock(&amp;aic-&gt;lock);
 	if (arq-&gt;is_sync == REQ_SYNC) {
-		set_bit(AS_TASK_IORUNNING, &amp;aic-&gt;state);
-		aic-&gt;last_end_request = jiffies;
+		struct as_io_context *aic = arq-&gt;io_context-&gt;aic;
+		if (aic) {
+			spin_lock(&amp;aic-&gt;lock);
+			set_bit(AS_TASK_IORUNNING, &amp;aic-&gt;state);
+			aic-&gt;last_end_request = jiffies;
+			spin_unlock(&amp;aic-&gt;lock);
+		}
 	}
-	spin_unlock(&amp;aic-&gt;lock);
 
 	put_io_context(arq-&gt;io_context);
+out:
+	arq-&gt;state = AS_RQ_POSTSCHED;
 }
 
 /*
@@ -1020,14 +1036,14 @@ static void as_remove_request(request_qu
 	struct as_rq *arq = RQ_DATA(rq);
 
 	if (unlikely(arq-&gt;state == AS_RQ_NEW))
-		return;
-
-	if (!arq) {
-		WARN_ON(1);
-		return;
-	}
+		goto out;
 
 	if (ON_RB(&amp;arq-&gt;rb_node)) {
+		if (arq-&gt;state != AS_RQ_QUEUED) {
+			printk("arq-&gt;state %d\n", arq-&gt;state);
+			WARN_ON(1);
+			goto out;
+		}
 		/*
 		 * We'll lose the aliased request(s) here. I don't think this
 		 * will ever happen, but if it does, hopefully someone will
@@ -1035,8 +1051,16 @@ static void as_remove_request(request_qu
 		 */
 		WARN_ON(!list_empty(&amp;rq-&gt;queuelist));
 		as_remove_queued_request(q, rq);
-	} else
+	} else {
+		if (arq-&gt;state != AS_RQ_DISPATCHED) {
+			printk("arq-&gt;state %d\n", arq-&gt;state);
+			WARN_ON(1);
+			goto out;
+		}
 		as_remove_dispatched_request(q, rq);
+	}
+out:
+	arq-&gt;state = AS_RQ_REMOVED;
 }
 
 /*
@@ -1214,9 +1238,9 @@ static int as_dispatch_request(struct as
 			 */
 			goto dispatch_writes;
 
- 		if (ad-&gt;batch_data_dir == REQ_ASYNC) {
+		if (ad-&gt;batch_data_dir == REQ_ASYNC) {
 			WARN_ON(ad-&gt;new_batch);
- 			ad-&gt;changed_batch = 1;
+			ad-&gt;changed_batch = 1;
 		}
 		ad-&gt;batch_data_dir = REQ_SYNC;
 		arq = list_entry_fifo(ad-&gt;fifo_list[ad-&gt;batch_data_dir].next);
@@ -1232,8 +1256,8 @@ static int as_dispatch_request(struct as
 dispatch_writes:
 		BUG_ON(RB_EMPTY(&amp;ad-&gt;sort_list[REQ_ASYNC]));
 
- 		if (ad-&gt;batch_data_dir == REQ_SYNC) {
- 			ad-&gt;changed_batch = 1;
+		if (ad-&gt;batch_data_dir == REQ_SYNC) {
+			ad-&gt;changed_batch = 1;
 
 			/*
 			 * new_batch might be 1 when the queue runs out of
@@ -1276,8 +1300,6 @@ fifo_expired:
 			ad-&gt;new_batch = 1;
 
 		ad-&gt;changed_batch = 0;
-
-//		arq-&gt;request-&gt;flags |= REQ_SOFTBARRIER;
 	}
 
 	/*
@@ -1402,6 +1424,11 @@ static void as_requeue_request(request_q
 	struct as_rq *arq = RQ_DATA(rq);
 
 	if (arq) {
+		if (arq-&gt;state != AS_RQ_REMOVED) {
+			printk("arq-&gt;state %d\n", arq-&gt;state);
+			WARN_ON(1);
+		}
+
 		arq-&gt;state = AS_RQ_DISPATCHED;
 		if (arq-&gt;io_context &amp;&amp; arq-&gt;io_context-&gt;aic)
 			atomic_inc(&amp;arq-&gt;io_context-&gt;aic-&gt;nr_dispatched);
@@ -1421,12 +1448,18 @@ as_insert_request(request_queue_t *q, st
 	struct as_data *ad = q-&gt;elevator.elevator_data;
 	struct as_rq *arq = RQ_DATA(rq);
 
-#if 0
+	if (arq) {
+		if (arq-&gt;state != AS_RQ_PRESCHED) {
+			printk("arq-&gt;state: %d\n", arq-&gt;state);
+			WARN_ON(1);
+		}
+		arq-&gt;state = AS_RQ_NEW;
+	}
+
 	/* barriers must flush the reorder queue */
 	if (unlikely(rq-&gt;flags &amp; (REQ_SOFTBARRIER | REQ_HARDBARRIER)
 			&amp;&amp; where == ELEVATOR_INSERT_SORT))
 		where = ELEVATOR_INSERT_BACK;
-#endif
 
 	switch (where) {
 		case ELEVATOR_INSERT_BACK:
@@ -1661,7 +1694,8 @@ as_merged_requests(request_queue_t *q, s
 	 * kill knowledge of next, this one is a goner
 	 */
 	as_remove_queued_request(q, next);
-	put_io_context(anext-&gt;io_context);
+
+	anext-&gt;state = AS_RQ_MERGED;
 }
 
 /*
@@ -1694,6 +1728,11 @@ static void as_put_request(request_queue
 		return;
 	}
 
+	if (arq-&gt;state != AS_RQ_POSTSCHED) {
+		printk("arq-&gt;state %d\n", arq-&gt;state);
+		WARN_ON(1);
+	}
+
 	mempool_free(arq, ad-&gt;arq_pool);
 	rq-&gt;elevator_private = NULL;
 }
@@ -1707,7 +1746,7 @@ static int as_set_request(request_queue_
 		memset(arq, 0, sizeof(*arq));
 		RB_CLEAR(&amp;arq-&gt;rb_node);
 		arq-&gt;request = rq;
-		arq-&gt;state = AS_RQ_NEW;
+		arq-&gt;state = AS_RQ_PRESCHED;
 		arq-&gt;io_context = NULL;
 		INIT_LIST_HEAD(&amp;arq-&gt;hash);
 		arq-&gt;on_hash = 0;

_
</pre></body></html>