[BLOCK] as-iosched: update alias handling
authorTejun Heo <htejun@gmail.com>
Fri, 11 Nov 2005 13:27:09 +0000 (14:27 +0100)
committerJens Axboe <axboe@nelson.home.kernel.dk>
Fri, 6 Jan 2006 08:39:03 +0000 (09:39 +0100)
Unlike other ioscheds, as-iosched handles alias by chaing them using
rq->queuelist.  As aliased requests are very rare in the first place,
this complicates merge/dispatch handling without meaningful
performance improvement.  This patch updates as-iosched to dump
aliased requests into dispatch queue as other ioscheds do.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jens Axboe <axboe@suse.de>
block/as-iosched.c

index 43fa2049568883d6b5c07cc304b77c93d3091abf..8da3cf66894c379b1b4908d94602c49f77cb473e 100644 (file)
@@ -182,6 +182,9 @@ struct as_rq {
 
 static kmem_cache_t *arq_pool;
 
+static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq);
+static void as_antic_stop(struct as_data *ad);
+
 /*
  * IO Context helper functions
  */
@@ -370,7 +373,7 @@ static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir)
  * existing request against the same sector), which can happen when using
  * direct IO, then return the alias.
  */
-static struct as_rq *as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
 {
        struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node;
        struct rb_node *parent = NULL;
@@ -397,6 +400,16 @@ static struct as_rq *as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
        return NULL;
 }
 
+static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+{
+       struct as_rq *alias;
+
+       while ((unlikely(alias = __as_add_arq_rb(ad, arq)))) {
+               as_move_to_dispatch(ad, alias);
+               as_antic_stop(ad);
+       }
+}
+
 static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq)
 {
        if (!ON_RB(&arq->rb_node)) {
@@ -1133,23 +1146,6 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
        /*
         * take it off the sort and fifo list, add to dispatch queue
         */
-       while (!list_empty(&rq->queuelist)) {
-               struct request *__rq = list_entry_rq(rq->queuelist.next);
-               struct as_rq *__arq = RQ_DATA(__rq);
-
-               list_del(&__rq->queuelist);
-
-               elv_dispatch_add_tail(ad->q, __rq);
-
-               if (__arq->io_context && __arq->io_context->aic)
-                       atomic_inc(&__arq->io_context->aic->nr_dispatched);
-
-               WARN_ON(__arq->state != AS_RQ_QUEUED);
-               __arq->state = AS_RQ_DISPATCHED;
-
-               ad->nr_dispatched++;
-       }
-
        as_remove_queued_request(ad->q, rq);
        WARN_ON(arq->state != AS_RQ_QUEUED);
 
@@ -1325,42 +1321,6 @@ fifo_expired:
        return 1;
 }
 
-/*
- * Add arq to a list behind alias
- */
-static inline void
-as_add_aliased_request(struct as_data *ad, struct as_rq *arq,
-                               struct as_rq *alias)
-{
-       struct request  *req = arq->request;
-       struct list_head *insert = alias->request->queuelist.prev;
-
-       /*
-        * Transfer list of aliases
-        */
-       while (!list_empty(&req->queuelist)) {
-               struct request *__rq = list_entry_rq(req->queuelist.next);
-               struct as_rq *__arq = RQ_DATA(__rq);
-
-               list_move_tail(&__rq->queuelist, &alias->request->queuelist);
-
-               WARN_ON(__arq->state != AS_RQ_QUEUED);
-       }
-
-       /*
-        * Another request with the same start sector on the rbtree.
-        * Link this request to that sector. They are untangled in
-        * as_move_to_dispatch
-        */
-       list_add(&arq->request->queuelist, insert);
-
-       /*
-        * Don't want to have to handle merges.
-        */
-       as_del_arq_hash(arq);
-       arq->request->flags |= REQ_NOMERGE;
-}
-
 /*
  * add arq to rbtree and fifo
  */
@@ -1368,7 +1328,6 @@ static void as_add_request(request_queue_t *q, struct request *rq)
 {
        struct as_data *ad = q->elevator->elevator_data;
        struct as_rq *arq = RQ_DATA(rq);
-       struct as_rq *alias;
        int data_dir;
 
        arq->state = AS_RQ_NEW;
@@ -1387,33 +1346,17 @@ static void as_add_request(request_queue_t *q, struct request *rq)
                atomic_inc(&arq->io_context->aic->nr_queued);
        }
 
-       alias = as_add_arq_rb(ad, arq);
-       if (!alias) {
-               /*
-                * set expire time (only used for reads) and add to fifo list
-                */
-               arq->expires = jiffies + ad->fifo_expire[data_dir];
-               list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
+       as_add_arq_rb(ad, arq);
+       if (rq_mergeable(arq->request))
+               as_add_arq_hash(ad, arq);
 
-               if (rq_mergeable(arq->request))
-                       as_add_arq_hash(ad, arq);
-               as_update_arq(ad, arq); /* keep state machine up to date */
-
-       } else {
-               as_add_aliased_request(ad, arq, alias);
-
-               /*
-                * have we been anticipating this request?
-                * or does it come from the same process as the one we are
-                * anticipating for?
-                */
-               if (ad->antic_status == ANTIC_WAIT_REQ
-                               || ad->antic_status == ANTIC_WAIT_NEXT) {
-                       if (as_can_break_anticipation(ad, arq))
-                               as_antic_stop(ad);
-               }
-       }
+       /*
+        * set expire time (only used for reads) and add to fifo list
+        */
+       arq->expires = jiffies + ad->fifo_expire[data_dir];
+       list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
 
+       as_update_arq(ad, arq); /* keep state machine up to date */
        arq->state = AS_RQ_QUEUED;
 }
 
@@ -1536,23 +1479,8 @@ static void as_merged_request(request_queue_t *q, struct request *req)
         * if the merge was a front merge, we need to reposition request
         */
        if (rq_rb_key(req) != arq->rb_key) {
-               struct as_rq *alias, *next_arq = NULL;
-
-               if (ad->next_arq[arq->is_sync] == arq)
-                       next_arq = as_find_next_arq(ad, arq);
-
-               /*
-                * Note! We should really be moving any old aliased requests
-                * off this request and try to insert them into the rbtree. We
-                * currently don't bother. Ditto the next function.
-                */
                as_del_arq_rb(ad, arq);
-               if ((alias = as_add_arq_rb(ad, arq))) {
-                       list_del_init(&arq->fifo);
-                       as_add_aliased_request(ad, arq, alias);
-                       if (next_arq)
-                               ad->next_arq[arq->is_sync] = next_arq;
-               }
+               as_add_arq_rb(ad, arq);
                /*
                 * Note! At this stage of this and the next function, our next
                 * request may not be optimal - eg the request may have "grown"
@@ -1579,18 +1507,8 @@ static void as_merged_requests(request_queue_t *q, struct request *req,
        as_add_arq_hash(ad, arq);
 
        if (rq_rb_key(req) != arq->rb_key) {
-               struct as_rq *alias, *next_arq = NULL;
-
-               if (ad->next_arq[arq->is_sync] == arq)
-                       next_arq = as_find_next_arq(ad, arq);
-
                as_del_arq_rb(ad, arq);
-               if ((alias = as_add_arq_rb(ad, arq))) {
-                       list_del_init(&arq->fifo);
-                       as_add_aliased_request(ad, arq, alias);
-                       if (next_arq)
-                               ad->next_arq[arq->is_sync] = next_arq;
-               }
+               as_add_arq_rb(ad, arq);
        }
 
        /*
@@ -1609,18 +1527,6 @@ static void as_merged_requests(request_queue_t *q, struct request *req,
                }
        }
 
-       /*
-        * Transfer list of aliases
-        */
-       while (!list_empty(&next->queuelist)) {
-               struct request *__rq = list_entry_rq(next->queuelist.next);
-               struct as_rq *__arq = RQ_DATA(__rq);
-
-               list_move_tail(&__rq->queuelist, &req->queuelist);
-
-               WARN_ON(__arq->state != AS_RQ_QUEUED);
-       }
-
        /*
         * kill knowledge of next, this one is a goner
         */