From: Jens Axboe <axboe@suse.de>

Here's a quickie that limits the queue depth to 1 by default, changable in
sysfs.  There's room for improvement, if you want to play with things like
increasing the depth when anticipation doesn't work anyways.

Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/block/as-iosched.c |   50 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+)

diff -puN drivers/block/as-iosched.c~as-limit-queue-depth drivers/block/as-iosched.c
--- 25/drivers/block/as-iosched.c~as-limit-queue-depth	2005-05-03 20:53:53.000000000 -0700
+++ 25-akpm/drivers/block/as-iosched.c	2005-05-03 20:53:53.000000000 -0700
@@ -59,6 +59,11 @@
 #define default_antic_expire ((HZ / 150) ? HZ / 150 : 1)
 
 /*
+ * max in-flight at the hardware level
+ */
+#define default_queue_depth (1)
+
+/*
  * Keep track of up to 20ms thinktimes. We can go as big as we like here,
  * however huge values tend to interfere and not decay fast enough. A program
  * might be in a non-io phase of operation. Waiting on user input for example,
@@ -126,6 +131,9 @@ struct as_data {
 	int ioc_finished; /* IO associated with io_context is finished */
 	int nr_dispatched;
 
+	unsigned long queue_depth;
+	int in_flight;
+
 	/*
 	 * settings that change how the i/o scheduler behaves
 	 */
@@ -175,6 +183,7 @@ struct as_rq {
 	unsigned long expires;
 
 	unsigned int is_sync;
+	unsigned int in_flight;
 	enum arq_state state;
 };
 
@@ -1018,6 +1027,13 @@ out_ioc:
 	put_io_context(arq->io_context);
 out:
 	arq->state = AS_RQ_POSTSCHED;
+
+	if (arq->in_flight) {
+		WARN_ON(!ad->in_flight);
+
+		arq->in_flight = 0;
+		ad->in_flight--;
+	}
 }
 
 /*
@@ -1363,6 +1379,7 @@ static struct request *as_next_request(r
 {
 	struct as_data *ad = q->elevator->elevator_data;
 	struct request *rq = NULL;
+	struct as_rq *arq;
 
 	/*
 	 * if there are still requests on the dispatch queue, grab the first
@@ -1370,6 +1387,24 @@ static struct request *as_next_request(r
 	if (!list_empty(ad->dispatch) || as_dispatch_request(ad))
 		rq = list_entry_rq(ad->dispatch->next);
 
+	/*
+	 * if no request was available, or if this isn't a normal fs request
+	 * just pass that to the driver
+	 */
+	if (!rq || ((arq = RQ_DATA(rq)) == NULL) || !blk_fs_request(rq))
+		return rq;
+
+	/*
+	 * allow this request, if we are not exceeding the queue depth set
+	 * by the user or if this request was already seen by the driver
+	 */
+	if (arq->in_flight)
+		return rq;
+	else if (ad->in_flight >= ad->queue_depth)
+		return NULL;
+
+	arq->in_flight = 1;
+	ad->in_flight++;
 	return rq;
 }
 
@@ -1469,6 +1504,12 @@ static void as_deactivate_request(reques
 	struct as_rq *arq = RQ_DATA(rq);
 
 	if (arq) {
+		if (arq->in_flight) {
+			WARN_ON(!ad->in_flight);
+
+			arq->in_flight = 0;
+			ad->in_flight--;
+		}
 		if (arq->state == AS_RQ_REMOVED) {
 			arq->state = AS_RQ_DISPATCHED;
 			if (arq->io_context && arq->io_context->aic)
@@ -1913,6 +1954,7 @@ static int as_init_queue(request_queue_t
 	ad->antic_expire = default_antic_expire;
 	ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
 	ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
+	ad->queue_depth = default_queue_depth;
 	e->elevator_data = ad;
 
 	ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
@@ -1976,6 +2018,7 @@ SHOW_FUNCTION(as_writeexpire_show, ad->f
 SHOW_FUNCTION(as_anticexpire_show, ad->antic_expire);
 SHOW_FUNCTION(as_read_batchexpire_show, ad->batch_expire[REQ_SYNC]);
 SHOW_FUNCTION(as_write_batchexpire_show, ad->batch_expire[REQ_ASYNC]);
+SHOW_FUNCTION(as_queue_depth_show, ad->queue_depth);
 #undef SHOW_FUNCTION
 
 #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX)				\
@@ -1996,6 +2039,7 @@ STORE_FUNCTION(as_read_batchexpire_store
 			&ad->batch_expire[REQ_SYNC], 0, INT_MAX);
 STORE_FUNCTION(as_write_batchexpire_store,
 			&ad->batch_expire[REQ_ASYNC], 0, INT_MAX);
+STORE_FUNCTION(as_queue_depth_store, &ad->queue_depth, 1, INT_MAX);
 #undef STORE_FUNCTION
 
 static struct as_fs_entry as_est_entry = {
@@ -2027,6 +2071,11 @@ static struct as_fs_entry as_write_batch
 	.show = as_write_batchexpire_show,
 	.store = as_write_batchexpire_store,
 };
+static struct as_fs_entry as_queue_depth_entry = {
+	.attr = {.name = "queue_depth", .mode = S_IRUGO | S_IWUSR },
+	.show = as_queue_depth_show,
+	.store = as_queue_depth_store,
+};
 
 static struct attribute *default_attrs[] = {
 	&as_est_entry.attr,
@@ -2035,6 +2084,7 @@ static struct attribute *default_attrs[]
 	&as_anticexpire_entry.attr,
 	&as_read_batchexpire_entry.attr,
 	&as_write_batchexpire_entry.attr,
+	&as_queue_depth_entry.attr,
 	NULL,
 };
 
_