aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Moyer <jmoyer@redhat.com>2009-10-23 17:14:49 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-10-26 09:34:46 -0400
commitb2c18e1e08a5a9663094d57bb4be2f02226ee61c (patch)
tree55c092706a0d8a9e645f245bf2ecc45c29ba5aa7
parentc30f33437c3f85ec48353a1ef811e148217a2aaf (diff)
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: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r--block/cfq-iosched.c68
-rw-r--r--include/linux/iocontext.h5
2 files changed, 33 insertions, 40 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 069a61017c02..78cc8ee5da41 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -112,6 +112,11 @@ struct cfq_queue {
112 unsigned short ioprio, org_ioprio; 112 unsigned short ioprio, org_ioprio;
113 unsigned short ioprio_class, org_ioprio_class; 113 unsigned short ioprio_class, org_ioprio_class;
114 114
115 unsigned int seek_samples;
116 u64 seek_total;
117 sector_t seek_mean;
118 sector_t last_request_pos;
119
115 pid_t pid; 120 pid_t pid;
116}; 121};
117 122
@@ -962,16 +967,16 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
962 return cfqd->last_position - blk_rq_pos(rq); 967 return cfqd->last_position - blk_rq_pos(rq);
963} 968}
964 969
965#define CIC_SEEK_THR 8 * 1024 970#define CFQQ_SEEK_THR 8 * 1024
966#define CIC_SEEKY(cic) ((cic)->seek_mean > CIC_SEEK_THR) 971#define CFQQ_SEEKY(cfqq) ((cfqq)->seek_mean > CFQQ_SEEK_THR)
967 972
968static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq) 973static inline int cfq_rq_close(struct cfq_data *cfqd, struct cfq_queue *cfqq,
974 struct request *rq)
969{ 975{
970 struct cfq_io_context *cic = cfqd->active_cic; 976 sector_t sdist = cfqq->seek_mean;
971 sector_t sdist = cic->seek_mean;
972 977
973 if (!sample_valid(cic->seek_samples)) 978 if (!sample_valid(cfqq->seek_samples))
974 sdist = CIC_SEEK_THR; 979 sdist = CFQQ_SEEK_THR;
975 980
976 return cfq_dist_from_last(cfqd, rq) <= sdist; 981 return cfq_dist_from_last(cfqd, rq) <= sdist;
977} 982}
@@ -1000,7 +1005,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
1000 * will contain the closest sector. 1005 * will contain the closest sector.
1001 */ 1006 */
1002 __cfqq = rb_entry(parent, struct cfq_queue, p_node); 1007 __cfqq = rb_entry(parent, struct cfq_queue, p_node);
1003 if (cfq_rq_close(cfqd, __cfqq->next_rq)) 1008 if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq))
1004 return __cfqq; 1009 return __cfqq;
1005 1010
1006 if (blk_rq_pos(__cfqq->next_rq) < sector) 1011 if (blk_rq_pos(__cfqq->next_rq) < sector)
@@ -1011,7 +1016,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
1011 return NULL; 1016 return NULL;
1012 1017
1013 __cfqq = rb_entry(node, struct cfq_queue, p_node); 1018 __cfqq = rb_entry(node, struct cfq_queue, p_node);
1014 if (cfq_rq_close(cfqd, __cfqq->next_rq)) 1019 if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq))
1015 return __cfqq; 1020 return __cfqq;
1016 1021
1017 return NULL; 1022 return NULL;
@@ -1034,13 +1039,6 @@ static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd,
1034 struct cfq_queue *cfqq; 1039 struct cfq_queue *cfqq;
1035 1040
1036 /* 1041 /*
1037 * A valid cfq_io_context is necessary to compare requests against
1038 * the seek_mean of the current cfqq.
1039 */
1040 if (!cfqd->active_cic)
1041 return NULL;
1042
1043 /*
1044 * We should notice if some of the queues are cooperating, eg 1042 * We should notice if some of the queues are cooperating, eg
1045 * working closely on the same area of the disk. In that case, 1043 * working closely on the same area of the disk. In that case,
1046 * we can group them together and don't waste time idling. 1044 * we can group them together and don't waste time idling.
@@ -1110,7 +1108,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
1110 * seeks. so allow a little bit of time for him to submit a new rq 1108 * seeks. so allow a little bit of time for him to submit a new rq
1111 */ 1109 */
1112 sl = cfqd->cfq_slice_idle; 1110 sl = cfqd->cfq_slice_idle;
1113 if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic)) 1111 if (sample_valid(cfqq->seek_samples) && CFQQ_SEEKY(cfqq))
1114 sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT)); 1112 sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT));
1115 1113
1116 mod_timer(&cfqd->idle_slice_timer, jiffies + sl); 1114 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} 1945}
1948 1946
1949static void 1947static void
1950cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic, 1948cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1951 struct request *rq) 1949 struct request *rq)
1952{ 1950{
1953 sector_t sdist; 1951 sector_t sdist;
1954 u64 total; 1952 u64 total;
1955 1953
1956 if (!cic->last_request_pos) 1954 if (!cfqq->last_request_pos)
1957 sdist = 0; 1955 sdist = 0;
1958 else if (cic->last_request_pos < blk_rq_pos(rq)) 1956 else if (cfqq->last_request_pos < blk_rq_pos(rq))
1959 sdist = blk_rq_pos(rq) - cic->last_request_pos; 1957 sdist = blk_rq_pos(rq) - cfqq->last_request_pos;
1960 else 1958 else
1961 sdist = cic->last_request_pos - blk_rq_pos(rq); 1959 sdist = cfqq->last_request_pos - blk_rq_pos(rq);
1962 1960
1963 /* 1961 /*
1964 * Don't allow the seek distance to get too large from the 1962 * Don't allow the seek distance to get too large from the
1965 * odd fragment, pagein, etc 1963 * odd fragment, pagein, etc
1966 */ 1964 */
1967 if (cic->seek_samples <= 60) /* second&third seek */ 1965 if (cfqq->seek_samples <= 60) /* second&third seek */
1968 sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*1024); 1966 sdist = min(sdist, (cfqq->seek_mean * 4) + 2*1024*1024);
1969 else 1967 else
1970 sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*64); 1968 sdist = min(sdist, (cfqq->seek_mean * 4) + 2*1024*64);
1971 1969
1972 cic->seek_samples = (7*cic->seek_samples + 256) / 8; 1970 cfqq->seek_samples = (7*cfqq->seek_samples + 256) / 8;
1973 cic->seek_total = (7*cic->seek_total + (u64)256*sdist) / 8; 1971 cfqq->seek_total = (7*cfqq->seek_total + (u64)256*sdist) / 8;
1974 total = cic->seek_total + (cic->seek_samples/2); 1972 total = cfqq->seek_total + (cfqq->seek_samples/2);
1975 do_div(total, cic->seek_samples); 1973 do_div(total, cfqq->seek_samples);
1976 cic->seek_mean = (sector_t)total; 1974 cfqq->seek_mean = (sector_t)total;
1977} 1975}
1978 1976
1979/* 1977/*
@@ -1995,11 +1993,11 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1995 enable_idle = old_idle = cfq_cfqq_idle_window(cfqq); 1993 enable_idle = old_idle = cfq_cfqq_idle_window(cfqq);
1996 1994
1997 if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle || 1995 if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
1998 (!cfqd->cfq_latency && cfqd->hw_tag && CIC_SEEKY(cic))) 1996 (!cfqd->cfq_latency && cfqd->hw_tag && CFQQ_SEEKY(cfqq)))
1999 enable_idle = 0; 1997 enable_idle = 0;
2000 else if (sample_valid(cic->ttime_samples)) { 1998 else if (sample_valid(cic->ttime_samples)) {
2001 unsigned int slice_idle = cfqd->cfq_slice_idle; 1999 unsigned int slice_idle = cfqd->cfq_slice_idle;
2002 if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic)) 2000 if (sample_valid(cfqq->seek_samples) && CFQQ_SEEKY(cfqq))
2003 slice_idle = msecs_to_jiffies(CFQ_MIN_TT); 2001 slice_idle = msecs_to_jiffies(CFQ_MIN_TT);
2004 if (cic->ttime_mean > slice_idle) 2002 if (cic->ttime_mean > slice_idle)
2005 enable_idle = 0; 2003 enable_idle = 0;
@@ -2066,7 +2064,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
2066 * if this request is as-good as one we would expect from the 2064 * if this request is as-good as one we would expect from the
2067 * current cfqq, let it preempt 2065 * current cfqq, let it preempt
2068 */ 2066 */
2069 if (cfq_rq_close(cfqd, rq)) 2067 if (cfq_rq_close(cfqd, cfqq, rq))
2070 return true; 2068 return true;
2071 2069
2072 return false; 2070 return false;
@@ -2108,10 +2106,10 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
2108 cfqq->meta_pending++; 2106 cfqq->meta_pending++;
2109 2107
2110 cfq_update_io_thinktime(cfqd, cic); 2108 cfq_update_io_thinktime(cfqd, cic);
2111 cfq_update_io_seektime(cfqd, cic, rq); 2109 cfq_update_io_seektime(cfqd, cfqq, rq);
2112 cfq_update_idle_window(cfqd, cfqq, cic); 2110 cfq_update_idle_window(cfqd, cfqq, cic);
2113 2111
2114 cic->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); 2112 cfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
2115 2113
2116 if (cfqq == cfqd->active_queue) { 2114 if (cfqq == cfqd->active_queue) {
2117 /* 2115 /*
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index 4da4a75c3f1e..eb73632440f1 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -40,16 +40,11 @@ struct cfq_io_context {
40 struct io_context *ioc; 40 struct io_context *ioc;
41 41
42 unsigned long last_end_request; 42 unsigned long last_end_request;
43 sector_t last_request_pos;
44 43
45 unsigned long ttime_total; 44 unsigned long ttime_total;
46 unsigned long ttime_samples; 45 unsigned long ttime_samples;
47 unsigned long ttime_mean; 46 unsigned long ttime_mean;
48 47
49 unsigned int seek_samples;
50 u64 seek_total;
51 sector_t seek_mean;
52
53 struct list_head queue_list; 48 struct list_head queue_list;
54 struct hlist_node cic_list; 49 struct hlist_node cic_list;
55 50