[PATCH] as-iosched: remove arq->is_sync member
[powerpc.git] / block / cfq-iosched.c
index e25223e..5e4bae7 100644 (file)
@@ -6,7 +6,6 @@
  *
  *  Copyright (C) 2003 Jens Axboe <axboe@suse.de>
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
 #include <linux/elevator.h>
@@ -42,27 +41,10 @@ static DEFINE_SPINLOCK(cfq_exit_lock);
 #define CFQ_QHASH_ENTRIES      (1 << CFQ_QHASH_SHIFT)
 #define list_entry_qhash(entry)        hlist_entry((entry), struct cfq_queue, cfq_hash)
 
-/*
- * for the hash of crq inside the cfqq
- */
-#define CFQ_MHASH_SHIFT                6
-#define CFQ_MHASH_BLOCK(sec)   ((sec) >> 3)
-#define CFQ_MHASH_ENTRIES      (1 << CFQ_MHASH_SHIFT)
-#define CFQ_MHASH_FN(sec)      hash_long(CFQ_MHASH_BLOCK(sec), CFQ_MHASH_SHIFT)
-#define rq_hash_key(rq)                ((rq)->sector + (rq)->nr_sectors)
-#define list_entry_hash(ptr)   hlist_entry((ptr), struct cfq_rq, hash)
-
 #define list_entry_cfqq(ptr)   list_entry((ptr), struct cfq_queue, cfq_list)
-#define list_entry_fifo(ptr)   list_entry((ptr), struct request, queuelist)
 
 #define RQ_DATA(rq)            (rq)->elevator_private
 
-/*
- * rb-tree defines
- */
-#define rb_entry_crq(node)     rb_entry((node), struct cfq_rq, rb_node)
-#define rq_rb_key(rq)          (rq)->sector
-
 static kmem_cache_t *crq_pool;
 static kmem_cache_t *cfq_pool;
 static kmem_cache_t *cfq_ioc_pool;
@@ -113,11 +95,6 @@ struct cfq_data {
         */
        struct hlist_head *cfq_hash;
 
-       /*
-        * global crq hash for all queues
-        */
-       struct hlist_head *crq_hash;
-
        mempool_t *crq_pool;
 
        int rq_in_driver;
@@ -201,10 +178,7 @@ struct cfq_queue {
 };
 
 struct cfq_rq {
-       struct rb_node rb_node;
-       sector_t rb_key;
        struct request *request;
-       struct hlist_node hash;
 
        struct cfq_queue *cfq_queue;
        struct cfq_io_context *io_context;
@@ -272,42 +246,6 @@ static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsi
 static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
 static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask);
 
-/*
- * lots of deadline iosched dupes, can be abstracted later...
- */
-static inline void cfq_del_crq_hash(struct cfq_rq *crq)
-{
-       hlist_del_init(&crq->hash);
-}
-
-static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
-{
-       const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
-
-       hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]);
-}
-
-static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
-{
-       struct hlist_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)];
-       struct hlist_node *entry, *next;
-
-       hlist_for_each_safe(entry, next, hash_list) {
-               struct cfq_rq *crq = list_entry_hash(entry);
-               struct request *__rq = crq->request;
-
-               if (!rq_mergeable(__rq)) {
-                       cfq_del_crq_hash(crq);
-                       continue;
-               }
-
-               if (rq_hash_key(__rq) == offset)
-                       return __rq;
-       }
-
-       return NULL;
-}
-
 /*
  * scheduler run of queue, if there are requests pending and no one in the
  * driver that will restart queueing
@@ -429,33 +367,27 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
  */
 static struct cfq_rq *
 cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-                 struct cfq_rq *last)
+                 struct cfq_rq *last_crq)
 {
-       struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
-       struct rb_node *rbnext, *rbprev;
+       struct request *last = last_crq->request;
+       struct rb_node *rbnext = rb_next(&last->rb_node);
+       struct rb_node *rbprev = rb_prev(&last->rb_node);
+       struct cfq_rq *next = NULL, *prev = NULL;
 
-       if (!(rbnext = rb_next(&last->rb_node))) {
-               rbnext = rb_first(&cfqq->sort_list);
-               if (rbnext == &last->rb_node)
-                       rbnext = NULL;
-       }
-
-       rbprev = rb_prev(&last->rb_node);
+       BUG_ON(RB_EMPTY_NODE(&last->rb_node));
 
        if (rbprev)
-               crq_prev = rb_entry_crq(rbprev);
-       if (rbnext)
-               crq_next = rb_entry_crq(rbnext);
+               prev = RQ_DATA(rb_entry_rq(rbprev));
 
-       return cfq_choose_req(cfqd, crq_next, crq_prev);
-}
-
-static void cfq_update_next_crq(struct cfq_rq *crq)
-{
-       struct cfq_queue *cfqq = crq->cfq_queue;
+       if (rbnext)
+               next = RQ_DATA(rb_entry_rq(rbnext));
+       else {
+               rbnext = rb_first(&cfqq->sort_list);
+               if (rbnext && rbnext != &last->rb_node)
+                       next = RQ_DATA(rb_entry_rq(rbnext));
+       }
 
-       if (cfqq->next_crq == crq)
-               cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq);
+       return cfq_choose_req(cfqd, next, prev);
 }
 
 static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
@@ -550,71 +482,34 @@ static inline void cfq_del_crq_rb(struct cfq_rq *crq)
        BUG_ON(!cfqq->queued[sync]);
        cfqq->queued[sync]--;
 
-       cfq_update_next_crq(crq);
-
-       rb_erase(&crq->rb_node, &cfqq->sort_list);
+       elv_rb_del(&cfqq->sort_list, crq->request);
 
        if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list))
                cfq_del_cfqq_rr(cfqd, cfqq);
 }
 
-static struct cfq_rq *
-__cfq_add_crq_rb(struct cfq_rq *crq)
-{
-       struct rb_node **p = &crq->cfq_queue->sort_list.rb_node;
-       struct rb_node *parent = NULL;
-       struct cfq_rq *__crq;
-
-       while (*p) {
-               parent = *p;
-               __crq = rb_entry_crq(parent);
-
-               if (crq->rb_key < __crq->rb_key)
-                       p = &(*p)->rb_left;
-               else if (crq->rb_key > __crq->rb_key)
-                       p = &(*p)->rb_right;
-               else
-                       return __crq;
-       }
-
-       rb_link_node(&crq->rb_node, parent, p);
-       return NULL;
-}
-
 static void cfq_add_crq_rb(struct cfq_rq *crq)
 {
        struct cfq_queue *cfqq = crq->cfq_queue;
        struct cfq_data *cfqd = cfqq->cfqd;
        struct request *rq = crq->request;
-       struct cfq_rq *__alias;
+       struct request *__alias;
 
-       crq->rb_key = rq_rb_key(rq);
        cfqq->queued[cfq_crq_is_sync(crq)]++;
 
        /*
         * looks a little odd, but the first insert might return an alias.
         * if that happens, put the alias on the dispatch list
         */
-       while ((__alias = __cfq_add_crq_rb(crq)) != NULL)
-               cfq_dispatch_insert(cfqd->queue, __alias);
-
-       rb_insert_color(&crq->rb_node, &cfqq->sort_list);
-
-       if (!cfq_cfqq_on_rr(cfqq))
-               cfq_add_cfqq_rr(cfqd, cfqq);
-
-       /*
-        * check if this request is a better next-serve candidate
-        */
-       cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
+       while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL)
+               cfq_dispatch_insert(cfqd->queue, RQ_DATA(__alias));
 }
 
 static inline void
 cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
 {
-       rb_erase(&crq->rb_node, &cfqq->sort_list);
+       elv_rb_del(&cfqq->sort_list, crq->request);
        cfqq->queued[cfq_crq_is_sync(crq)]--;
-
        cfq_add_crq_rb(crq);
 }
 
@@ -623,28 +518,13 @@ cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
 {
        struct task_struct *tsk = current;
        pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio));
+       sector_t sector = bio->bi_sector + bio_sectors(bio);
        struct cfq_queue *cfqq;
-       struct rb_node *n;
-       sector_t sector;
 
        cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
-       if (!cfqq)
-               goto out;
-
-       sector = bio->bi_sector + bio_sectors(bio);
-       n = cfqq->sort_list.rb_node;
-       while (n) {
-               struct cfq_rq *crq = rb_entry_crq(n);
-
-               if (sector < crq->rb_key)
-                       n = n->rb_left;
-               else if (sector > crq->rb_key)
-                       n = n->rb_right;
-               else
-                       return crq->request;
-       }
+       if (cfqq)
+               return elv_rb_find(&cfqq->sort_list, sector);
 
-out:
        return NULL;
 }
 
@@ -675,10 +555,13 @@ static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
 static void cfq_remove_request(struct request *rq)
 {
        struct cfq_rq *crq = RQ_DATA(rq);
+       struct cfq_queue *cfqq = crq->cfq_queue;
+
+       if (cfqq->next_crq == crq)
+               cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq);
 
        list_del_init(&rq->queuelist);
        cfq_del_crq_rb(crq);
-       cfq_del_crq_hash(crq);
 }
 
 static int
@@ -686,38 +569,24 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct request *__rq;
-       int ret;
-
-       __rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
-       if (__rq && elv_rq_merge_ok(__rq, bio)) {
-               ret = ELEVATOR_BACK_MERGE;
-               goto out;
-       }
 
        __rq = cfq_find_rq_fmerge(cfqd, bio);
        if (__rq && elv_rq_merge_ok(__rq, bio)) {
-               ret = ELEVATOR_FRONT_MERGE;
-               goto out;
+               *req = __rq;
+               return ELEVATOR_FRONT_MERGE;
        }
 
        return ELEVATOR_NO_MERGE;
-out:
-       *req = __rq;
-       return ret;
 }
 
-static void cfq_merged_request(request_queue_t *q, struct request *req)
+static void cfq_merged_request(request_queue_t *q, struct request *req,
+                              int type)
 {
-       struct cfq_data *cfqd = q->elevator->elevator_data;
        struct cfq_rq *crq = RQ_DATA(req);
 
-       cfq_del_crq_hash(crq);
-       cfq_add_crq_hash(cfqd, crq);
-
-       if (rq_rb_key(req) != crq->rb_key) {
+       if (type == ELEVATOR_FRONT_MERGE) {
                struct cfq_queue *cfqq = crq->cfq_queue;
 
-               cfq_update_next_crq(crq);
                cfq_reposition_crq_rb(cfqq, crq);
        }
 }
@@ -726,8 +595,6 @@ static void
 cfq_merged_requests(request_queue_t *q, struct request *rq,
                    struct request *next)
 {
-       cfq_merged_request(q, rq);
-
        /*
         * reposition in fifo if next is older than rq
         */
@@ -937,7 +804,7 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
         * seeks. so allow a little bit of time for him to submit a new rq
         */
        if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
-               sl = 2;
+               sl = min(sl, msecs_to_jiffies(2));
 
        mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
        return 1;
@@ -949,7 +816,6 @@ static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
        struct cfq_queue *cfqq = crq->cfq_queue;
        struct request *rq;
 
-       cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
        cfq_remove_request(crq->request);
        cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
        elv_dispatch_sort(q, crq->request);
@@ -973,7 +839,7 @@ static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq)
        if (!list_empty(&cfqq->fifo)) {
                int fifo = cfq_cfqq_class_sync(cfqq);
 
-               crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next));
+               crq = RQ_DATA(rq_entry_fifo(cfqq->fifo.next));
                rq = crq->request;
                if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) {
                        cfq_mark_cfqq_fifo_expire(cfqq);
@@ -1562,7 +1428,7 @@ restart:
                /* ->key must be copied to avoid race with cfq_exit_queue() */
                k = __cic->key;
                if (unlikely(!k)) {
-                       cfq_drop_dead_cic(ioc, cic);
+                       cfq_drop_dead_cic(ioc, __cic);
                        goto restart;
                }
 
@@ -1767,6 +1633,12 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 {
        struct cfq_io_context *cic = crq->io_context;
 
+       /*
+        * check if this request is a better next-serve candidate
+        */
+       cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
+       BUG_ON(!cfqq->next_crq);
+
        /*
         * we never wait for an async request and we don't allow preemption
         * of an async request. so just return early
@@ -1824,10 +1696,10 @@ static void cfq_insert_request(request_queue_t *q, struct request *rq)
 
        cfq_add_crq_rb(crq);
 
-       list_add_tail(&rq->queuelist, &cfqq->fifo);
+       if (!cfq_cfqq_on_rr(cfqq))
+               cfq_add_cfqq_rr(cfqd, cfqq);
 
-       if (rq_mergeable(rq))
-               cfq_add_crq_hash(cfqd, crq);
+       list_add_tail(&rq->queuelist, &cfqq->fifo);
 
        cfq_crq_enqueued(cfqd, cfqq, crq);
 }
@@ -1874,30 +1746,6 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq)
        }
 }
 
-static struct request *
-cfq_former_request(request_queue_t *q, struct request *rq)
-{
-       struct cfq_rq *crq = RQ_DATA(rq);
-       struct rb_node *rbprev = rb_prev(&crq->rb_node);
-
-       if (rbprev)
-               return rb_entry_crq(rbprev)->request;
-
-       return NULL;
-}
-
-static struct request *
-cfq_latter_request(request_queue_t *q, struct request *rq)
-{
-       struct cfq_rq *crq = RQ_DATA(rq);
-       struct rb_node *rbnext = rb_next(&crq->rb_node);
-
-       if (rbnext)
-               return rb_entry_crq(rbnext)->request;
-
-       return NULL;
-}
-
 /*
  * we temporarily boost lower priority queues if they are holding fs exclusive
  * resources. they are boosted to normal prio (CLASS_BE/4)
@@ -2053,10 +1901,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
 
        crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
        if (crq) {
-               RB_CLEAR_NODE(&crq->rb_node);
-               crq->rb_key = 0;
                crq->request = rq;
-               INIT_HLIST_NODE(&crq->hash);
                crq->cfq_queue = cfqq;
                crq->io_context = cic;
 
@@ -2222,7 +2067,6 @@ static void cfq_exit_queue(elevator_t *e)
        cfq_shutdown_timer_wq(cfqd);
 
        mempool_destroy(cfqd->crq_pool);
-       kfree(cfqd->crq_hash);
        kfree(cfqd->cfq_hash);
        kfree(cfqd);
 }
@@ -2247,20 +2091,14 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
        INIT_LIST_HEAD(&cfqd->empty_list);
        INIT_LIST_HEAD(&cfqd->cic_list);
 
-       cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
-       if (!cfqd->crq_hash)
-               goto out_crqhash;
-
        cfqd->cfq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL);
        if (!cfqd->cfq_hash)
-               goto out_cfqhash;
+               goto out_crqhash;
 
        cfqd->crq_pool = mempool_create_slab_pool(BLKDEV_MIN_RQ, crq_pool);
        if (!cfqd->crq_pool)
                goto out_crqpool;
 
-       for (i = 0; i < CFQ_MHASH_ENTRIES; i++)
-               INIT_HLIST_HEAD(&cfqd->crq_hash[i]);
        for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
                INIT_HLIST_HEAD(&cfqd->cfq_hash[i]);
 
@@ -2290,8 +2128,6 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
        return cfqd;
 out_crqpool:
        kfree(cfqd->cfq_hash);
-out_cfqhash:
-       kfree(cfqd->crq_hash);
 out_crqhash:
        kfree(cfqd);
        return NULL;
@@ -2426,8 +2262,8 @@ static struct elevator_type iosched_cfq = {
                .elevator_deactivate_req_fn =   cfq_deactivate_request,
                .elevator_queue_empty_fn =      cfq_queue_empty,
                .elevator_completed_req_fn =    cfq_completed_request,
-               .elevator_former_req_fn =       cfq_former_request,
-               .elevator_latter_req_fn =       cfq_latter_request,
+               .elevator_former_req_fn =       elv_rb_former_request,
+               .elevator_latter_req_fn =       elv_rb_latter_request,
                .elevator_set_req_fn =          cfq_set_request,
                .elevator_put_req_fn =          cfq_put_request,
                .elevator_may_queue_fn =        cfq_may_queue,