Commit b2c18e1e authored by Jeff Moyer's avatar Jeff Moyer Committed by Jens Axboe

cfq: calculate the seek_mean per cfq_queue not per cfq_io_context

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: default avatarJeff Moyer <jmoyer@redhat.com>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent c30f3343
...@@ -112,6 +112,11 @@ struct cfq_queue { ...@@ -112,6 +112,11 @@ struct cfq_queue {
unsigned short ioprio, org_ioprio; unsigned short ioprio, org_ioprio;
unsigned short ioprio_class, org_ioprio_class; 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; pid_t pid;
}; };
...@@ -962,16 +967,16 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd, ...@@ -962,16 +967,16 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
return cfqd->last_position - blk_rq_pos(rq); return cfqd->last_position - blk_rq_pos(rq);
} }
#define CIC_SEEK_THR 8 * 1024 #define CFQQ_SEEK_THR 8 * 1024
#define CIC_SEEKY(cic) ((cic)->seek_mean > CIC_SEEK_THR) #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 = cfqq->seek_mean;
sector_t sdist = cic->seek_mean;
if (!sample_valid(cic->seek_samples)) if (!sample_valid(cfqq->seek_samples))
sdist = CIC_SEEK_THR; sdist = CFQQ_SEEK_THR;
return cfq_dist_from_last(cfqd, rq) <= sdist; return cfq_dist_from_last(cfqd, rq) <= sdist;
} }
...@@ -1000,7 +1005,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, ...@@ -1000,7 +1005,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
* will contain the closest sector. * will contain the closest sector.
*/ */
__cfqq = rb_entry(parent, struct cfq_queue, p_node); __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; return __cfqq;
if (blk_rq_pos(__cfqq->next_rq) < sector) if (blk_rq_pos(__cfqq->next_rq) < sector)
...@@ -1011,7 +1016,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, ...@@ -1011,7 +1016,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
return NULL; return NULL;
__cfqq = rb_entry(node, struct cfq_queue, p_node); __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 __cfqq;
return NULL; return NULL;
...@@ -1033,13 +1038,6 @@ static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd, ...@@ -1033,13 +1038,6 @@ static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd,
{ {
struct cfq_queue *cfqq; 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 * We should notice if some of the queues are cooperating, eg
* working closely on the same area of the disk. In that case, * working closely on the same area of the disk. In that case,
...@@ -1110,7 +1108,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) ...@@ -1110,7 +1108,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 * seeks. so allow a little bit of time for him to submit a new rq
*/ */
sl = cfqd->cfq_slice_idle; 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)); sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT));
mod_timer(&cfqd->idle_slice_timer, jiffies + sl); mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
...@@ -1947,33 +1945,33 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic) ...@@ -1947,33 +1945,33 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
} }
static void 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) struct request *rq)
{ {
sector_t sdist; sector_t sdist;
u64 total; u64 total;
if (!cic->last_request_pos) if (!cfqq->last_request_pos)
sdist = 0; sdist = 0;
else if (cic->last_request_pos < blk_rq_pos(rq)) else if (cfqq->last_request_pos < blk_rq_pos(rq))
sdist = blk_rq_pos(rq) - cic->last_request_pos; sdist = blk_rq_pos(rq) - cfqq->last_request_pos;
else 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 * Don't allow the seek distance to get too large from the
* odd fragment, pagein, etc * odd fragment, pagein, etc
*/ */
if (cic->seek_samples <= 60) /* second&third seek */ if (cfqq->seek_samples <= 60) /* second&third seek */
sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*1024); sdist = min(sdist, (cfqq->seek_mean * 4) + 2*1024*1024);
else 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; cfqq->seek_samples = (7*cfqq->seek_samples + 256) / 8;
cic->seek_total = (7*cic->seek_total + (u64)256*sdist) / 8; cfqq->seek_total = (7*cfqq->seek_total + (u64)256*sdist) / 8;
total = cic->seek_total + (cic->seek_samples/2); total = cfqq->seek_total + (cfqq->seek_samples/2);
do_div(total, cic->seek_samples); do_div(total, cfqq->seek_samples);
cic->seek_mean = (sector_t)total; cfqq->seek_mean = (sector_t)total;
} }
/* /*
...@@ -1995,11 +1993,11 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, ...@@ -1995,11 +1993,11 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
enable_idle = old_idle = cfq_cfqq_idle_window(cfqq); enable_idle = old_idle = cfq_cfqq_idle_window(cfqq);
if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle || 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; enable_idle = 0;
else if (sample_valid(cic->ttime_samples)) { else if (sample_valid(cic->ttime_samples)) {
unsigned int slice_idle = cfqd->cfq_slice_idle; 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); slice_idle = msecs_to_jiffies(CFQ_MIN_TT);
if (cic->ttime_mean > slice_idle) if (cic->ttime_mean > slice_idle)
enable_idle = 0; enable_idle = 0;
...@@ -2066,7 +2064,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, ...@@ -2066,7 +2064,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 * if this request is as-good as one we would expect from the
* current cfqq, let it preempt * current cfqq, let it preempt
*/ */
if (cfq_rq_close(cfqd, rq)) if (cfq_rq_close(cfqd, cfqq, rq))
return true; return true;
return false; return false;
...@@ -2108,10 +2106,10 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, ...@@ -2108,10 +2106,10 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
cfqq->meta_pending++; cfqq->meta_pending++;
cfq_update_io_thinktime(cfqd, cic); 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); 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) { if (cfqq == cfqd->active_queue) {
/* /*
......
...@@ -40,16 +40,11 @@ struct cfq_io_context { ...@@ -40,16 +40,11 @@ struct cfq_io_context {
struct io_context *ioc; struct io_context *ioc;
unsigned long last_end_request; unsigned long last_end_request;
sector_t last_request_pos;
unsigned long ttime_total; unsigned long ttime_total;
unsigned long ttime_samples; unsigned long ttime_samples;
unsigned long ttime_mean; unsigned long ttime_mean;
unsigned int seek_samples;
u64 seek_total;
sector_t seek_mean;
struct list_head queue_list; struct list_head queue_list;
struct hlist_node cic_list; struct hlist_node cic_list;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment