DESC
antsched: commentary and 


 block/as-iosched.c |  150 ++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 98 insertions(+), 52 deletions(-)

diff -puN drivers/block/as-iosched.c~as-comments-and-tweaks drivers/block/as-iosched.c
--- 25/drivers/block/as-iosched.c~as-comments-and-tweaks	2003-02-20 23:20:20.000000000 -0800
+++ 25-akpm/drivers/block/as-iosched.c	2003-02-20 23:20:20.000000000 -0800
@@ -89,13 +89,10 @@ static const int as_hash_shift = 10;
 			(dd)->hash_valid_count = 1;	\
 	} while (0)
 
-/*
- * Nick!  These need descriptions
- */
-#define ANTIC_OFF	0
-#define ANTIC_WAIT	1
-#define ANTIC_TIMEOUT	2
-#define ANTIC_FOUND	3
+#define ANTIC_OFF	0	/* Not anticipating (normal operation)	*/
+#define ANTIC_WAIT	1	/* Currently anticipating a request	*/
+#define ANTIC_FINISHED	2	/* Anticipating but have found a candidate
+				   or timed out	*/
 
 struct as_data {
 	/*
@@ -592,6 +589,19 @@ static int as_fifo_expired(struct as_dat
 	return time_after(jiffies, drq->expires);
 }
 
+static int as_antic_expired(struct as_data *dd)
+{
+	long delta_jif;
+
+	delta_jif = jiffies - dd->antic_start;
+	if (unlikely(delta_jif < 0))
+		delta_jif = -delta_jif;
+	if (delta_jif < dd->antic_expire)
+		return 0;
+
+	return 1;
+}
+
 /*
  * as_batch_expired returns true if the current batch has expired.
  */
@@ -638,8 +648,7 @@ static void as_anticipate_timeout(unsign
 
 	spin_lock_irqsave(q->queue_lock, flags);
 
-	if (dd->antic_status != ANTIC_FOUND)
-		dd->antic_status = ANTIC_TIMEOUT;
+	dd->antic_status = ANTIC_FINISHED;
 
 	blk_remove_plug(q);
 	schedule_work(&dd->antic_work);
@@ -662,10 +671,10 @@ as_close_req(struct as_data *dd, struct 
 	
 	sector_t delta;	/* acceptable close offset (in sectors) */
 
-	if (dd->antic_status == ANTIC_OFF || delay <= 2)
-		delta = 64;
-	else if (delay <= dd->antic_expire / 2)
-		delta = 64 << ((delay - 2)*2);
+	if (dd->antic_status == ANTIC_OFF || delay <= 1)
+		delta = 32;
+	else if (delay <= 20 && delay <= dd->antic_expire / 2)
+		delta = 32 << (delay-1);
 	else
 		return 1;
 
@@ -695,43 +704,30 @@ as_choose_req(struct as_data *dd,
 	BUG_ON(data_dir != rq_data_dir(drq2->request));
 
 	/*
-	 * Nick: boggle.  What algorithm is this implementing?
-	 */
-	if (data_dir == READ) {
-		if (s1 >= last)
-			d1 = s1 - last;
-		else {
-			/* count large back seeks as a forward seek */
-			if (dd->current_id == drq1->request_id && s1+maxback >= last)
+	 * Strict one way elevator _except_ in the case where we allow
+	 * short backward seeks which are biased as twice the cost of a
+	 * similar forward seek. Only for reads and only between reads
+	 * from the same process!
+	 */
+	if (s1 >= last)
+		d1 = s1 - last;
+	else if (data_dir == READ
+			&& dd->current_id == drq1->request_id
+			&& s1+maxback >= last)
 				d1 = (last - s1)*2;
-			else
-				d1 = (last - s1)*8;
-		}
+	else
+		goto elevator_wrap;
 
-		if (s2 >= last)
-			d2 = s2 - last;
-		else {
-			if (dd->current_id == drq2->request_id && s2+maxback >= last)
+	if (s2 >= last)
+		d2 = s2 - last;
+	else if (data_dir == READ
+			&& dd->current_id == drq2->request_id
+			&& s2+maxback >= last)
 				d2 = (last - s2)*2;
-			else
-				d2 = (last - s2)*8;
-		}
-	} else { /* data_dir == WRITE */
-		if (s1 >= last && s2 >= last) {
-			d1 = s1 - last;
-			d2 = s2 - last;
-		} else if (s1 >= last && s2 < last) {
-			d1 = s1 - last;
-			d2 = d1+1;
-		} else if (s2 >= last && s1 < last) {
-			d2 = s2 - last;
-			d1 = d2+1;
-		} else {
-			d1 = s1;
-			d2 = s2;
-		}
-	}
+	else
+		goto elevator_wrap;
 
+	/* Found the deltas */
 	if (d1 < d2)
 		return drq1;
 	else if (d2 < d1)
@@ -742,6 +738,25 @@ as_choose_req(struct as_data *dd,
 		else
 			return drq2;
 	}
+	
+elevator_wrap:
+	/*
+	 * a request is behind the disk head, in most
+	 * cases this is treated as the elevator wrapping
+	 * to the start, so a lower valued request (further away)
+	 * is favourable
+	 */
+	if (s1 >= last && s2 < last)
+		return drq1;
+	else if (s2 >= last && s1 < last)
+		return drq2;
+	else {
+		/* both behind the head */
+		if (s1 <= s2)
+			return drq1;
+		else
+			return drq2;
+	}
 }
 
 /*
@@ -810,25 +825,46 @@ as_update_drq(struct as_data *dd, struct
 			ant_stats.lba_forward_offsets[log2]++;
 
 		del_timer(&dd->antic_timer);
-		dd->antic_status = ANTIC_FOUND;
+		dd->antic_status = ANTIC_FINISHED;
 		blk_remove_plug(drq->request->q);
 		schedule_work(&dd->antic_work);
 	}
 }
 
 /*
- * argh.  Nick, can you please comment every clause in this function?
+ * can_start_anticipation indicates weather we should either run drq
+ * or keep anticipating a better request.
  */
 static int
 can_start_anticipation(struct as_data *dd, struct as_rq *drq)
 {
-	if (dd->antic_status == ANTIC_FOUND)
+	if (dd->antic_status == ANTIC_FINISHED)
+		/*
+		 * Don't restart if we have just finished. Run the next request
+		 */
 		return 0;
-	if (!(dd->antic_status == ANTIC_OFF ||
-		time_before(jiffies, dd->antic_start + dd->antic_expire)))
+	
+	if (dd->antic_status == ANTIC_WAIT && as_antic_expired(dd))
+		/*
+		 * In this situation status should really be FINISHED, however
+		 * the timer hasn't had the chance to run yet.
+		 */
 		return 0;
+
 	if (drq && as_antic_req(dd, drq))
+		/*
+		 * This request is a good candidate. Don't keep anticipating,
+		 * run it.
+		 */
 		return 0;
+
+	/*
+	 * OK from here, we haven't finished, haven't timed out, and don't
+	 * have a decent request!
+	 * status is either ANTIC_WAIT or ANTIC_OFF. So we'll either keep
+	 * waiting or start waiting respectively.
+	 */
+
 	return 1;
 }
 
@@ -843,6 +879,8 @@ static int as_dispatch_request(struct re
 	struct as_rq *drq;
 	const int reads = !list_empty(&dd->fifo_list[READ]);
 	const int writes = !list_empty(&dd->fifo_list[WRITE]);
+	static unsigned long last_read_id;
+	static unsigned long last_finished;
 
 	if (!(reads || writes))
 		return 0;
@@ -956,6 +994,14 @@ fifo_expired:
 	 */
 	dd->antic_status = ANTIC_OFF;
 	as_move_request(dd, drq);
+
+	if (dd->batch_data_dir == READ) {
+		if (last_read_id != drq->request_id) {
+			last_read_id = drq->request_id;
+		}
+		last_finished = drq->request->sector + drq->request->nr_sectors;
+	}
+	
 	return 1;
 }
 
@@ -992,7 +1038,7 @@ as_insert_request(request_queue_t *q, st
 		
 		if (rq_data_dir(rq) == READ && dd->antic_status != ANTIC_OFF) {
 			del_timer(&dd->antic_timer);
-			dd->antic_status = ANTIC_FOUND;
+			dd->antic_status = ANTIC_FINISHED;
 			blk_remove_plug(q);
 			schedule_work(&dd->antic_work);
 		}

_