This patch introduces "cfq_driver_Data" structure.
  This structure extract driver unique data from "cfq_data" structure.


    Signed-off-by: Satoshi UCHIDA <[EMAIL PROTECTED]>

---
 block/cfq-iosched.c         |  218 ++++++++++++++++++++++++++-----------------
 include/linux/cfq-iosched.h |   32 ++++---
 2 files changed, 151 insertions(+), 99 deletions(-)

diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 024d392..b726e85 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -144,9 +144,10 @@ CFQ_CFQQ_FNS(sync);
 #undef CFQ_CFQQ_FNS
 
 #define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \
-       blk_add_trace_msg((cfqd)->queue, "cfq%d " fmt, (cfqq)->pid, ##args)
+       blk_add_trace_msg((cfqd)->cfqdd->queue, \
+                         "cfq%d " fmt, (cfqq)->pid, ##args)
 #define cfq_log(cfqd, fmt, args...)    \
-       blk_add_trace_msg((cfqd)->queue, "cfq " fmt, ##args)
+       blk_add_trace_msg((cfqd)->cfqdd->queue, "cfq " fmt, ##args)
 
 static void cfq_dispatch_insert(struct request_queue *, struct request *);
 static struct cfq_queue *cfq_get_queue(struct cfq_data *, int,
@@ -184,9 +185,11 @@ static inline int cfq_bio_sync(struct bio *bio)
  */
 static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
 {
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        if (cfqd->busy_queues) {
                cfq_log(cfqd, "schedule dispatch");
-               kblockd_schedule_work(cfqd->queue, &cfqd->unplug_work);
+               kblockd_schedule_work(cfqdd->queue,
+                                     &cfqdd->unplug_work);
        }
 }
 
@@ -271,7 +274,7 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, 
struct request *rq2)
        s1 = rq1->sector;
        s2 = rq2->sector;
 
-       last = cfqd->last_position;
+       last = cfqd->cfqdd->last_position;
 
        /*
         * by definition, 1KiB is 2 sectors
@@ -548,7 +551,7 @@ static void cfq_add_rq_rb(struct request *rq)
         * if that happens, put the alias on the dispatch list
         */
        while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL)
-               cfq_dispatch_insert(cfqd->queue, __alias);
+               cfq_dispatch_insert(cfqd->cfqdd->queue, __alias);
 
        if (!cfq_cfqq_on_rr(cfqq))
                cfq_add_cfqq_rr(cfqd, cfqq);
@@ -591,22 +594,24 @@ cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
 static void cfq_activate_request(struct request_queue *q, struct request *rq)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
 
-       cfqd->rq_in_driver++;
+       cfqdd->rq_in_driver++;
        cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "activate rq, drv=%d",
-                                               cfqd->rq_in_driver);
+                                               cfqdd->rq_in_driver);
 
-       cfqd->last_position = rq->hard_sector + rq->hard_nr_sectors;
+       cfqdd->last_position = rq->hard_sector + rq->hard_nr_sectors;
 }
 
 static void cfq_deactivate_request(struct request_queue *q, struct request *rq)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
 
-       WARN_ON(!cfqd->rq_in_driver);
-       cfqd->rq_in_driver--;
+       WARN_ON(!cfqdd->rq_in_driver);
+       cfqdd->rq_in_driver--;
        cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "deactivate rq, drv=%d",
-                                               cfqd->rq_in_driver);
+                                               cfqdd->rq_in_driver);
 }
 
 static void cfq_remove_request(struct request *rq)
@@ -619,7 +624,7 @@ static void cfq_remove_request(struct request *rq)
        list_del_init(&rq->queuelist);
        cfq_del_rq_rb(rq);
 
-       cfqq->cfqd->rq_queued--;
+       cfqq->cfqd->cfqdd->rq_queued--;
        if (rq_is_meta(rq)) {
                WARN_ON(!cfqq->meta_pending);
                cfqq->meta_pending--;
@@ -715,10 +720,12 @@ static void
 __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                    int timed_out)
 {
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
+
        cfq_log_cfqq(cfqd, cfqq, "slice expired t=%d", timed_out);
 
        if (cfq_cfqq_wait_request(cfqq))
-               del_timer(&cfqd->idle_slice_timer);
+               del_timer(&cfqdd->idle_slice_timer);
 
        cfq_clear_cfqq_must_dispatch(cfqq);
        cfq_clear_cfqq_wait_request(cfqq);
@@ -736,9 +743,9 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue 
*cfqq,
        if (cfqq == cfqd->active_queue)
                cfqd->active_queue = NULL;
 
-       if (cfqd->active_cic) {
-               put_io_context(cfqd->active_cic->ioc);
-               cfqd->active_cic = NULL;
+       if (cfqdd->active_cic) {
+               put_io_context(cfqdd->active_cic->ioc);
+               cfqdd->active_cic = NULL;
        }
 }
 
@@ -777,15 +784,17 @@ static struct cfq_queue *cfq_set_active_queue(struct 
cfq_data *cfqd)
 static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
                                          struct request *rq)
 {
-       if (rq->sector >= cfqd->last_position)
-               return rq->sector - cfqd->last_position;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
+
+       if (rq->sector >= cfqdd->last_position)
+               return rq->sector - cfqdd->last_position;
        else
-               return cfqd->last_position - rq->sector;
+               return cfqdd->last_position - rq->sector;
 }
 
 static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq)
 {
-       struct cfq_io_context *cic = cfqd->active_cic;
+       struct cfq_io_context *cic = cfqd->cfqdd->active_cic;
 
        if (!sample_valid(cic->seek_samples))
                return 0;
@@ -809,6 +818,7 @@ static int cfq_close_cooperator(struct cfq_data *cfq_data,
 static void cfq_arm_slice_timer(struct cfq_data *cfqd)
 {
        struct cfq_queue *cfqq = cfqd->active_queue;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        struct cfq_io_context *cic;
        unsigned long sl;
 
@@ -817,7 +827,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
         * for devices that support queuing, otherwise we still have a problem
         * with sync vs async workloads.
         */
-       if (blk_queue_nonrot(cfqd->queue) && cfqd->hw_tag)
+       if (blk_queue_nonrot(cfqdd->queue) && cfqdd->hw_tag)
                return;
 
        WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list));
@@ -832,13 +842,13 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
        /*
         * still requests with the driver, don't idle
         */
-       if (cfqd->rq_in_driver)
+       if (cfqdd->rq_in_driver)
                return;
 
        /*
         * task has exited, don't wait
         */
-       cic = cfqd->active_cic;
+       cic = cfqdd->active_cic;
        if (!cic || !atomic_read(&cic->ioc->nr_tasks))
                return;
 
@@ -861,7 +871,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
        if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
                sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT));
 
-       mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
+       mod_timer(&cfqdd->idle_slice_timer, jiffies + sl);
        cfq_log(cfqd, "arm_idle: %lu", sl);
 }
 
@@ -880,7 +890,7 @@ static void cfq_dispatch_insert(struct request_queue *q, 
struct request *rq)
        elv_dispatch_sort(q, rq);
 
        if (cfq_cfqq_sync(cfqq))
-               cfqd->sync_flight++;
+               cfqd->cfqdd->sync_flight++;
 }
 
 /*
@@ -950,7 +960,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data 
*cfqd)
         * flight or is idling for a new request, allow either of these
         * conditions to happen (or time out) before selecting a new queue.
         */
-       if (timer_pending(&cfqd->idle_slice_timer) ||
+       if (timer_pending(&cfqd->cfqdd->idle_slice_timer) ||
            (cfqq->dispatched && cfq_cfqq_idle_window(cfqq))) {
                cfqq = NULL;
                goto keep_queue;
@@ -972,6 +982,7 @@ static int
 __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                        int max_dispatch)
 {
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        int dispatched = 0;
 
        BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
@@ -989,13 +1000,13 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct 
cfq_queue *cfqq,
                /*
                 * finally, insert request into driver dispatch list
                 */
-               cfq_dispatch_insert(cfqd->queue, rq);
+               cfq_dispatch_insert(cfqdd->queue, rq);
 
                dispatched++;
 
-               if (!cfqd->active_cic) {
+               if (!cfqdd->active_cic) {
                        atomic_inc(&RQ_CIC(rq)->ioc->refcount);
-                       cfqd->active_cic = RQ_CIC(rq);
+                       cfqdd->active_cic = RQ_CIC(rq);
                }
 
                if (RB_EMPTY_ROOT(&cfqq->sort_list))
@@ -1022,7 +1033,7 @@ static int __cfq_forced_dispatch_cfqq(struct cfq_queue 
*cfqq)
        int dispatched = 0;
 
        while (cfqq->next_rq) {
-               cfq_dispatch_insert(cfqq->cfqd->queue, cfqq->next_rq);
+               cfq_dispatch_insert(cfqq->cfqd->cfqdd->queue, cfqq->next_rq);
                dispatched++;
        }
 
@@ -1054,6 +1065,7 @@ static int cfq_dispatch_requests(struct request_queue *q, 
int force)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct cfq_queue *cfqq;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        int dispatched;
 
        if (!cfqd->busy_queues)
@@ -1077,12 +1089,12 @@ static int cfq_dispatch_requests(struct request_queue 
*q, int force)
                                break;
                }
 
-               if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq))
+               if (cfqdd->sync_flight && !cfq_cfqq_sync(cfqq))
                        break;
 
                cfq_clear_cfqq_must_dispatch(cfqq);
                cfq_clear_cfqq_wait_request(cfqq);
-               del_timer(&cfqd->idle_slice_timer);
+               del_timer(&cfqdd->idle_slice_timer);
 
                dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
        }
@@ -1248,7 +1260,7 @@ static void cfq_exit_single_io_context(struct io_context 
*ioc,
        struct cfq_data *cfqd = cic->key;
 
        if (cfqd) {
-               struct request_queue *q = cfqd->queue;
+               struct request_queue *q = cfqd->cfqdd->queue;
                unsigned long flags;
 
                spin_lock_irqsave(q->queue_lock, flags);
@@ -1272,7 +1284,7 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t 
gfp_mask)
        struct cfq_io_context *cic;
 
        cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask | __GFP_ZERO,
-                                                       cfqd->queue->node);
+                                               cfqd->cfqdd->queue->node);
        if (cic) {
                cic->last_end_request = jiffies;
                INIT_LIST_HEAD(&cic->queue_list);
@@ -1332,12 +1344,13 @@ static void changed_ioprio(struct io_context *ioc, 
struct cfq_io_context *cic)
 {
        struct cfq_data *cfqd = cic->key;
        struct cfq_queue *cfqq;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        unsigned long flags;
 
        if (unlikely(!cfqd))
                return;
 
-       spin_lock_irqsave(cfqd->queue->queue_lock, flags);
+       spin_lock_irqsave(cfqdd->queue->queue_lock, flags);
 
        cfqq = cic->cfqq[ASYNC];
        if (cfqq) {
@@ -1353,7 +1366,7 @@ static void changed_ioprio(struct io_context *ioc, struct 
cfq_io_context *cic)
        if (cfqq)
                cfq_mark_cfqq_prio_changed(cfqq);
 
-       spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
+       spin_unlock_irqrestore(cfqdd->queue->queue_lock, flags);
 }
 
 static void cfq_ioc_set_ioprio(struct io_context *ioc)
@@ -1367,6 +1380,7 @@ cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
                     struct io_context *ioc, gfp_t gfp_mask)
 {
        struct cfq_queue *cfqq, *new_cfqq = NULL;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        struct cfq_io_context *cic;
 
 retry:
@@ -1385,16 +1399,16 @@ retry:
                         * the allocator to do whatever it needs to attempt to
                         * free memory.
                         */
-                       spin_unlock_irq(cfqd->queue->queue_lock);
+                       spin_unlock_irq(cfqdd->queue->queue_lock);
                        new_cfqq = kmem_cache_alloc_node(cfq_pool,
                                        gfp_mask | __GFP_NOFAIL | __GFP_ZERO,
-                                       cfqd->queue->node);
-                       spin_lock_irq(cfqd->queue->queue_lock);
+                                       cfqdd->queue->node);
+                       spin_lock_irq(cfqdd->queue->queue_lock);
                        goto retry;
                } else {
                        cfqq = kmem_cache_alloc_node(cfq_pool,
                                        gfp_mask | __GFP_ZERO,
-                                       cfqd->queue->node);
+                                       cfqdd->queue->node);
                        if (!cfqq)
                                goto out;
                }
@@ -1547,9 +1561,11 @@ cfq_cic_lookup(struct cfq_data *cfqd, struct io_context 
*ioc)
 static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
                        struct cfq_io_context *cic, gfp_t gfp_mask)
 {
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        unsigned long flags;
        int ret;
 
+
        ret = radix_tree_preload(gfp_mask);
        if (!ret) {
                cic->ioc = ioc;
@@ -1565,9 +1581,11 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct 
io_context *ioc,
                radix_tree_preload_end();
 
                if (!ret) {
-                       spin_lock_irqsave(cfqd->queue->queue_lock, flags);
+                       spin_lock_irqsave(cfqdd->queue->queue_lock,
+                                               flags);
                        list_add(&cic->queue_list, &cfqd->cic_list);
-                       spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
+                       spin_unlock_irqrestore(cfqdd->queue->queue_lock,
+                                               flags);
                }
        }
 
@@ -1590,7 +1608,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 
        might_sleep_if(gfp_mask & __GFP_WAIT);
 
-       ioc = get_io_context(gfp_mask, cfqd->queue->node);
+       ioc = get_io_context(gfp_mask, cfqd->cfqdd->queue->node);
        if (!ioc)
                return NULL;
 
@@ -1676,7 +1694,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct 
cfq_queue *cfqq,
        enable_idle = old_idle = cfq_cfqq_idle_window(cfqq);
 
        if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
-           (cfqd->hw_tag && CIC_SEEKY(cic)))
+           (cfqd->cfqdd->hw_tag && CIC_SEEKY(cic)))
                enable_idle = 0;
        else if (sample_valid(cic->ttime_samples)) {
                if (cic->ttime_mean > cfqd->cfq_slice_idle)
@@ -1731,7 +1749,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct 
cfq_queue *new_cfqq,
        if (rq_is_meta(rq) && !cfqq->meta_pending)
                return 1;
 
-       if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
+       if (!cfqd->cfqdd->active_cic || !cfq_cfqq_wait_request(cfqq))
                return 0;
 
        /*
@@ -1774,8 +1792,9 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue 
*cfqq,
                struct request *rq)
 {
        struct cfq_io_context *cic = RQ_CIC(rq);
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
 
-       cfqd->rq_queued++;
+       cfqdd->rq_queued++;
        if (rq_is_meta(rq))
                cfqq->meta_pending++;
 
@@ -1793,8 +1812,8 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue 
*cfqq,
                 */
                if (cfq_cfqq_wait_request(cfqq)) {
                        cfq_mark_cfqq_must_dispatch(cfqq);
-                       del_timer(&cfqd->idle_slice_timer);
-                       blk_start_queueing(cfqd->queue);
+                       del_timer(&cfqdd->idle_slice_timer);
+                       blk_start_queueing(cfqdd->queue);
                }
        } else if (cfq_should_preempt(cfqd, cfqq, rq)) {
                /*
@@ -1804,7 +1823,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue 
*cfqq,
                 */
                cfq_preempt_queue(cfqd, cfqq);
                cfq_mark_cfqq_must_dispatch(cfqq);
-               blk_start_queueing(cfqd->queue);
+               blk_start_queueing(cfqdd->queue);
        }
 }
 
@@ -1827,49 +1846,50 @@ static void cfq_insert_request(struct request_queue *q, 
struct request *rq)
  * Update hw_tag based on peak queue depth over 50 samples under
  * sufficient load.
  */
-static void cfq_update_hw_tag(struct cfq_data *cfqd)
+static void cfq_update_hw_tag(struct cfq_driver_data *cfqdd)
 {
-       if (cfqd->rq_in_driver > cfqd->rq_in_driver_peak)
-               cfqd->rq_in_driver_peak = cfqd->rq_in_driver;
+       if (cfqdd->rq_in_driver > cfqdd->rq_in_driver_peak)
+               cfqdd->rq_in_driver_peak = cfqdd->rq_in_driver;
 
-       if (cfqd->rq_queued <= CFQ_HW_QUEUE_MIN &&
-           cfqd->rq_in_driver <= CFQ_HW_QUEUE_MIN)
+       if (cfqdd->rq_queued <= CFQ_HW_QUEUE_MIN &&
+           cfqdd->rq_in_driver <= CFQ_HW_QUEUE_MIN)
                return;
 
-       if (cfqd->hw_tag_samples++ < 50)
+       if (cfqdd->hw_tag_samples++ < 50)
                return;
 
-       if (cfqd->rq_in_driver_peak >= CFQ_HW_QUEUE_MIN)
-               cfqd->hw_tag = 1;
+       if (cfqdd->rq_in_driver_peak >= CFQ_HW_QUEUE_MIN)
+               cfqdd->hw_tag = 1;
        else
-               cfqd->hw_tag = 0;
+               cfqdd->hw_tag = 0;
 
-       cfqd->hw_tag_samples = 0;
-       cfqd->rq_in_driver_peak = 0;
+       cfqdd->hw_tag_samples = 0;
+       cfqdd->rq_in_driver_peak = 0;
 }
 
 static void cfq_completed_request(struct request_queue *q, struct request *rq)
 {
        struct cfq_queue *cfqq = RQ_CFQQ(rq);
        struct cfq_data *cfqd = cfqq->cfqd;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        const int sync = rq_is_sync(rq);
        unsigned long now;
 
        now = jiffies;
        cfq_log_cfqq(cfqd, cfqq, "complete");
 
-       cfq_update_hw_tag(cfqd);
+       cfq_update_hw_tag(cfqdd);
 
-       WARN_ON(!cfqd->rq_in_driver);
+       WARN_ON(!cfqdd->rq_in_driver);
        WARN_ON(!cfqq->dispatched);
-       cfqd->rq_in_driver--;
+       cfqdd->rq_in_driver--;
        cfqq->dispatched--;
 
        if (cfq_cfqq_sync(cfqq))
-               cfqd->sync_flight--;
+               cfqdd->sync_flight--;
 
        if (!cfq_class_idle(cfqq))
-               cfqd->last_end_request = now;
+               cfqdd->last_end_request = now;
 
        if (sync)
                RQ_CIC(rq)->last_end_request = now;
@@ -1889,7 +1909,7 @@ static void cfq_completed_request(struct request_queue 
*q, struct request *rq)
                        cfq_arm_slice_timer(cfqd);
        }
 
-       if (!cfqd->rq_in_driver)
+       if (!cfqdd->rq_in_driver)
                cfq_schedule_dispatch(cfqd);
 }
 
@@ -2034,9 +2054,9 @@ queue_fail:
 
 static void cfq_kick_queue(struct work_struct *work)
 {
-       struct cfq_data *cfqd =
-               container_of(work, struct cfq_data, unplug_work);
-       struct request_queue *q = cfqd->queue;
+       struct cfq_driver_data *cfqdd =
+               container_of(work, struct cfq_driver_data, unplug_work);
+       struct request_queue *q = cfqdd->queue;
        unsigned long flags;
 
        spin_lock_irqsave(q->queue_lock, flags);
@@ -2051,12 +2071,13 @@ static void cfq_idle_slice_timer(unsigned long data)
 {
        struct cfq_data *cfqd = (struct cfq_data *) data;
        struct cfq_queue *cfqq;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
        unsigned long flags;
        int timed_out = 1;
 
        cfq_log(cfqd, "idle timer fired");
 
-       spin_lock_irqsave(cfqd->queue->queue_lock, flags);
+       spin_lock_irqsave(cfqdd->queue->queue_lock, flags);
 
        cfqq = cfqd->active_queue;
        if (cfqq) {
@@ -2088,13 +2109,13 @@ expire:
 out_kick:
        cfq_schedule_dispatch(cfqd);
 out_cont:
-       spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
+       spin_unlock_irqrestore(cfqdd->queue->queue_lock, flags);
 }
 
-static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
+static void cfq_shutdown_timer_wq(struct cfq_driver_data *cfqdd)
 {
-       del_timer_sync(&cfqd->idle_slice_timer);
-       kblockd_flush_work(&cfqd->unplug_work);
+       del_timer_sync(&cfqdd->idle_slice_timer);
+       kblockd_flush_work(&cfqdd->unplug_work);
 }
 
 static void cfq_put_async_queues(struct cfq_data *cfqd)
@@ -2115,9 +2136,10 @@ static void cfq_put_async_queues(struct cfq_data *cfqd)
 static void cfq_exit_queue(elevator_t *e)
 {
        struct cfq_data *cfqd = e->elevator_data;
-       struct request_queue *q = cfqd->queue;
+       struct cfq_driver_data *cfqdd = cfqd->cfqdd;
+       struct request_queue *q = cfqdd->queue;
 
-       cfq_shutdown_timer_wq(cfqd);
+       cfq_shutdown_timer_wq(cfqdd);
 
        spin_lock_irq(q->queue_lock);
 
@@ -2136,11 +2158,37 @@ static void cfq_exit_queue(elevator_t *e)
 
        spin_unlock_irq(q->queue_lock);
 
-       cfq_shutdown_timer_wq(cfqd);
+       cfq_shutdown_timer_wq(cfqdd);
 
+       kfree(cfqdd);
        kfree(cfqd);
 }
 
+static struct cfq_driver_data *
+cfq_init_driver_data(struct request_queue *q, struct cfq_data *cfqd)
+{
+       struct cfq_driver_data *cfqdd;
+
+       cfqdd = kmalloc_node(sizeof(*cfqdd),
+                                  GFP_KERNEL | __GFP_ZERO, q->node);
+       if (!cfqdd)
+               return NULL;
+
+       cfqdd->queue = q;
+
+       init_timer(&cfqdd->idle_slice_timer);
+       cfqdd->idle_slice_timer.function = cfq_idle_slice_timer;
+       cfqdd->idle_slice_timer.data = (unsigned long) cfqd;
+
+       INIT_WORK(&cfqdd->unplug_work, cfq_kick_queue);
+
+       cfqdd->last_end_request = jiffies;
+
+       cfqdd->hw_tag = 1;
+
+       return cfqdd;
+}
+
 static void *cfq_init_queue(struct request_queue *q)
 {
        struct cfq_data *cfqd;
@@ -2149,18 +2197,15 @@ static void *cfq_init_queue(struct request_queue *q)
        if (!cfqd)
                return NULL;
 
+       cfqd->cfqdd = cfq_init_driver_data(q, cfqd);
+       if (!cfqd->cfqdd) {
+               kfree(cfqd);
+               return NULL;
+       }
+
        cfqd->service_tree = CFQ_RB_ROOT;
        INIT_LIST_HEAD(&cfqd->cic_list);
 
-       cfqd->queue = q;
-
-       init_timer(&cfqd->idle_slice_timer);
-       cfqd->idle_slice_timer.function = cfq_idle_slice_timer;
-       cfqd->idle_slice_timer.data = (unsigned long) cfqd;
-
-       INIT_WORK(&cfqd->unplug_work, cfq_kick_queue);
-
-       cfqd->last_end_request = jiffies;
        cfqd->cfq_quantum = cfq_quantum;
        cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
        cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1];
@@ -2170,7 +2215,6 @@ static void *cfq_init_queue(struct request_queue *q)
        cfqd->cfq_slice[1] = cfq_slice_sync;
        cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
        cfqd->cfq_slice_idle = cfq_slice_idle;
-       cfqd->hw_tag = 1;
 
        return cfqd;
 }
diff --git a/include/linux/cfq-iosched.h b/include/linux/cfq-iosched.h
index adb2410..50003f7 100644
--- a/include/linux/cfq-iosched.h
+++ b/include/linux/cfq-iosched.h
@@ -20,17 +20,11 @@ struct cfq_rb_root {
 #define CFQ_RB_ROOT    (struct cfq_rb_root) { RB_ROOT, NULL, }
 
 /*
- * Per block device queue structure
+ * Driver unique data structure
  */
-struct cfq_data {
+struct cfq_driver_data {
        struct request_queue *queue;
 
-       /*
-        * rr list of queues with requests and the count of them
-        */
-       struct cfq_rb_root service_tree;
-       unsigned int busy_queues;
-
        int rq_in_driver;
        int sync_flight;
 
@@ -48,18 +42,30 @@ struct cfq_data {
        struct timer_list idle_slice_timer;
        struct work_struct unplug_work;
 
-       struct cfq_queue *active_queue;
        struct cfq_io_context *active_cic;
 
+       sector_t last_position;
+       unsigned long last_end_request;
+};
+
+/*
+ * Per block device queue structure
+ */
+struct cfq_data {
+       /*
+        * rr list of queues with requests and the count of them
+        */
+       struct cfq_rb_root service_tree;
+       unsigned int busy_queues;
+
+       struct cfq_queue *active_queue;
+
        /*
         * async queue for each priority case
         */
        struct cfq_queue *async_cfqq[2][IOPRIO_BE_NR];
        struct cfq_queue *async_idle_cfqq;
 
-       sector_t last_position;
-       unsigned long last_end_request;
-
        /*
         * tunables, see top of file
         */
@@ -72,6 +78,8 @@ struct cfq_data {
        unsigned int cfq_slice_idle;
 
        struct list_head cic_list;
+
+       struct cfq_driver_data *cfqdd;
 };
 
 #endif  /* _LINUX_CFQ_IOSCHED_H */
-- 
1.5.6.5


_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/virtualization

Reply via email to