cfq: calculate the seek_mean per cfq_queue not per cfq_io_context
authorJeff Moyer <jmoyer@redhat.com>
Thu, 29 Sep 2011 09:56:58 +0000 (15:26 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 7 Nov 2011 20:32:38 +0000 (12:32 -0800)
commit b2c18e1e08a5a9663094d57bb4be2f02226ee61c upstream.

async cfq_queue's are already shared between processes within the same
priority, and forthcoming patches will change the mapping of cic to sync
cfq_queue from 1:1 to 1:N.  So, calculate the seekiness of a process
based on the cfq_queue instead of the cfq_io_context.

Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
block/cfq-iosched.c
include/linux/iocontext.h

index 847c9476c20d8ab445c3d24233acd302907763a9..3b8847b3ab37798394355f1ddc5af08f0db90153 100644 (file)
@@ -112,6 +112,11 @@ struct cfq_queue {
        unsigned short ioprio, org_ioprio;
        unsigned short ioprio_class, org_ioprio_class;
 
+       unsigned int seek_samples;
+       u64 seek_total;
+       sector_t seek_mean;
+       sector_t last_request_pos;
+
        pid_t pid;
 };
 
@@ -967,16 +972,16 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
                return cfqd->last_position - blk_rq_pos(rq);
 }
 
-#define CIC_SEEK_THR   8 * 1024
-#define CIC_SEEKY(cic) ((cic)->seek_mean > CIC_SEEK_THR)
+#define CFQQ_SEEK_THR          8 * 1024
+#define CFQQ_SEEKY(cfqq)       ((cfqq)->seek_mean > CFQQ_SEEK_THR)
 
-static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq)
+static inline int cfq_rq_close(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+                              struct request *rq)
 {
-       struct cfq_io_context *cic = cfqd->active_cic;
-       sector_t sdist = cic->seek_mean;
+       sector_t sdist = cfqq->seek_mean;
 
-       if (!sample_valid(cic->seek_samples))
-               sdist = CIC_SEEK_THR;
+       if (!sample_valid(cfqq->seek_samples))
+               sdist = CFQQ_SEEK_THR;
 
        return cfq_dist_from_last(cfqd, rq) <= sdist;
 }
@@ -1005,7 +1010,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
         * will contain the closest sector.
         */
        __cfqq = rb_entry(parent, struct cfq_queue, p_node);
-       if (cfq_rq_close(cfqd, __cfqq->next_rq))
+       if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq))
                return __cfqq;
 
        if (blk_rq_pos(__cfqq->next_rq) < sector)
@@ -1016,7 +1021,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
                return NULL;
 
        __cfqq = rb_entry(node, struct cfq_queue, p_node);
-       if (cfq_rq_close(cfqd, __cfqq->next_rq))
+       if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq))
                return __cfqq;
 
        return NULL;
@@ -1038,13 +1043,6 @@ static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd,
 {
        struct cfq_queue *cfqq;
 
-       /*
-        * A valid cfq_io_context is necessary to compare requests against
-        * the seek_mean of the current cfqq.
-        */
-       if (!cfqd->active_cic)
-               return NULL;
-
        /*
         * We should notice if some of the queues are cooperating, eg
         * working closely on the same area of the disk. In that case,
@@ -1115,7 +1113,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
         * seeks. so allow a little bit of time for him to submit a new rq
         */
        sl = cfqd->cfq_slice_idle;
-       if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
+       if (sample_valid(cfqq->seek_samples) && CFQQ_SEEKY(cfqq))
                sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT));
 
        mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
@@ -1958,33 +1956,33 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
 }
 
 static void
-cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
+cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                       struct request *rq)
 {
        sector_t sdist;
        u64 total;
 
-       if (!cic->last_request_pos)
+       if (!cfqq->last_request_pos)
                sdist = 0;
-       else if (cic->last_request_pos < blk_rq_pos(rq))
-               sdist = blk_rq_pos(rq) - cic->last_request_pos;
+       else if (cfqq->last_request_pos < blk_rq_pos(rq))
+               sdist = blk_rq_pos(rq) - cfqq->last_request_pos;
        else
-               sdist = cic->last_request_pos - blk_rq_pos(rq);
+               sdist = cfqq->last_request_pos - blk_rq_pos(rq);
 
        /*
         * Don't allow the seek distance to get too large from the
         * odd fragment, pagein, etc
         */
-       if (cic->seek_samples <= 60) /* second&third seek */
-               sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*1024);
+       if (cfqq->seek_samples <= 60) /* second&third seek */
+               sdist = min(sdist, (cfqq->seek_mean * 4) + 2*1024*1024);
        else
-               sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*64);
+               sdist = min(sdist, (cfqq->seek_mean * 4) + 2*1024*64);
 
-       cic->seek_samples = (7*cic->seek_samples + 256) / 8;
-       cic->seek_total = (7*cic->seek_total + (u64)256*sdist) / 8;
-       total = cic->seek_total + (cic->seek_samples/2);
-       do_div(total, cic->seek_samples);
-       cic->seek_mean = (sector_t)total;
+       cfqq->seek_samples = (7*cfqq->seek_samples + 256) / 8;
+       cfqq->seek_total = (7*cfqq->seek_total + (u64)256*sdist) / 8;
+       total = cfqq->seek_total + (cfqq->seek_samples/2);
+       do_div(total, cfqq->seek_samples);
+       cfqq->seek_mean = (sector_t)total;
 }
 
 /*
@@ -2006,11 +2004,11 @@ 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->cfq_latency && cfqd->hw_tag && CIC_SEEKY(cic)))
+           (!cfqd->cfq_latency && cfqd->hw_tag && CFQQ_SEEKY(cfqq)))
                enable_idle = 0;
        else if (sample_valid(cic->ttime_samples)) {
                unsigned int slice_idle = cfqd->cfq_slice_idle;
-               if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
+               if (sample_valid(cfqq->seek_samples) && CFQQ_SEEKY(cfqq))
                        slice_idle = msecs_to_jiffies(CFQ_MIN_TT);
                if (cic->ttime_mean > slice_idle)
                        enable_idle = 0;
@@ -2077,7 +2075,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
         * if this request is as-good as one we would expect from the
         * current cfqq, let it preempt
         */
-       if (cfq_rq_close(cfqd, rq) && (!cfq_cfqq_coop(new_cfqq) ||
+       if (cfq_rq_close(cfqd, cfqq, rq) && (!cfq_cfqq_coop(new_cfqq) ||
            cfqd->busy_queues == 1)) {
                /*
                 * Mark new queue coop_preempt, so its coop flag will not be
@@ -2127,10 +2125,10 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                cfqq->meta_pending++;
 
        cfq_update_io_thinktime(cfqd, cic);
-       cfq_update_io_seektime(cfqd, cic, rq);
+       cfq_update_io_seektime(cfqd, cfqq, rq);
        cfq_update_idle_window(cfqd, cfqq, cic);
 
-       cic->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
+       cfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
 
        if (cfqq == cfqd->active_queue) {
                /*
index 4da4a75c3f1e7df3690f83c102bef5cdd824f7b5..eb73632440f1eee64aeca31b05dba6dced7e3508 100644 (file)
@@ -40,16 +40,11 @@ struct cfq_io_context {
        struct io_context *ioc;
 
        unsigned long last_end_request;
-       sector_t last_request_pos;
 
        unsigned long ttime_total;
        unsigned long ttime_samples;
        unsigned long ttime_mean;
 
-       unsigned int seek_samples;
-       u64 seek_total;
-       sector_t seek_mean;
-
        struct list_head queue_list;
        struct hlist_node cic_list;