The problem is that a task completes a read and then submits a write.  But it
still has readahead in flight.  We start anticipation on the back of that
readahead, but fail to notice that this task has just submitted a write.



 drivers/block/as-iosched.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

diff -puN drivers/block/as-iosched.c~as-break-if-readahead drivers/block/as-iosched.c
--- 25/drivers/block/as-iosched.c~as-break-if-readahead	Mon Feb 24 15:09:27 2003
+++ 25-akpm/drivers/block/as-iosched.c	Mon Feb 24 15:10:21 2003
@@ -750,14 +750,14 @@ elevator_wrap:
 }
 
 /*
- * as_antic_req returns true if we have been anticipating this request.
+ * as_break_anticipation returns true if we have been anticipating this request.
  *
  * It also returns true if the process against which we are anticipating
  * submits a write - that's presumably an fsync, O_SYNC write, etc. We want to
  * dispatch it ASAP, because we know that application will not be submitting
  * any new reads.
  */
-static int as_antic_req(struct as_data *ad, struct as_rq *arq)
+static int as_break_anticipation(struct as_data *ad, struct as_rq *arq)
 {
 	if (rq_data_dir(arq->request) == READ && as_close_req(ad, arq)) {
 		ant_stats.close_requests++;
@@ -794,7 +794,8 @@ static void as_update_arq(struct as_data
 	 * or does it come from the same process as the one we are anticipating
 	 * for?
 	 */
-	if (ad->antic_status != ANTIC_OFF && as_antic_req(ad, arq)) {
+	if (ad->antic_status != ANTIC_FINISHED
+			&& as_break_anticipation(ad, arq)) {
 		sector_t last = ad->last_sector[data_dir];
 		sector_t this = arq->request->sector;
 		unsigned long delay = jiffies - ad->antic_start;
@@ -821,11 +822,14 @@ static void as_update_arq(struct as_data
 			else
 				ant_stats.lba_forward_offsets[log2]++;
 		}
-		del_timer(&ad->antic_timer);
+
+		if (ad->antic_status == ANTIC_WAIT) {
+			del_timer(&ad->antic_timer);
+			if (arq)
+				blk_remove_plug(arq->request->q);
+			schedule_work(&ad->antic_work);
+		}
 		ad->antic_status = ANTIC_FINISHED;
-		if (arq)
-			blk_remove_plug(arq->request->q);
-		schedule_work(&ad->antic_work);
 	}
 }
 
@@ -853,7 +857,7 @@ static int can_start_anticipation(struct
 		return 0;
 	}
 
-	if (arq && as_antic_req(ad, arq))
+	if (arq && as_break_anticipation(ad, arq))
 		/*
 		 * This request is a good candidate. Don't keep anticipating,
 		 * run it.

_