aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c48
1 files changed, 12 insertions, 36 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index d9bfa09e68c1..8df4fe58f4e7 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -292,8 +292,7 @@ static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd);
292 292
293static struct cfq_rb_root *service_tree_for(struct cfq_group *cfqg, 293static struct cfq_rb_root *service_tree_for(struct cfq_group *cfqg,
294 enum wl_prio_t prio, 294 enum wl_prio_t prio,
295 enum wl_type_t type, 295 enum wl_type_t type)
296 struct cfq_data *cfqd)
297{ 296{
298 if (!cfqg) 297 if (!cfqg)
299 return NULL; 298 return NULL;
@@ -1146,7 +1145,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1146#endif 1145#endif
1147 1146
1148 service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq), 1147 service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq),
1149 cfqq_type(cfqq), cfqd); 1148 cfqq_type(cfqq));
1150 if (cfq_class_idle(cfqq)) { 1149 if (cfq_class_idle(cfqq)) {
1151 rb_key = CFQ_IDLE_DELAY; 1150 rb_key = CFQ_IDLE_DELAY;
1152 parent = rb_last(&service_tree->rb); 1151 parent = rb_last(&service_tree->rb);
@@ -1609,7 +1608,7 @@ static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd)
1609{ 1608{
1610 struct cfq_rb_root *service_tree = 1609 struct cfq_rb_root *service_tree =
1611 service_tree_for(cfqd->serving_group, cfqd->serving_prio, 1610 service_tree_for(cfqd->serving_group, cfqd->serving_prio,
1612 cfqd->serving_type, cfqd); 1611 cfqd->serving_type);
1613 1612
1614 if (!cfqd->rq_queued) 1613 if (!cfqd->rq_queued)
1615 return NULL; 1614 return NULL;
@@ -1956,8 +1955,7 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq)
1956} 1955}
1957 1956
1958static enum wl_type_t cfq_choose_wl(struct cfq_data *cfqd, 1957static enum wl_type_t cfq_choose_wl(struct cfq_data *cfqd,
1959 struct cfq_group *cfqg, enum wl_prio_t prio, 1958 struct cfq_group *cfqg, enum wl_prio_t prio)
1960 bool prio_changed)
1961{ 1959{
1962 struct cfq_queue *queue; 1960 struct cfq_queue *queue;
1963 int i; 1961 int i;
@@ -1965,24 +1963,9 @@ static enum wl_type_t cfq_choose_wl(struct cfq_data *cfqd,
1965 unsigned long lowest_key = 0; 1963 unsigned long lowest_key = 0;
1966 enum wl_type_t cur_best = SYNC_NOIDLE_WORKLOAD; 1964 enum wl_type_t cur_best = SYNC_NOIDLE_WORKLOAD;
1967 1965
1968 if (prio_changed) { 1966 for (i = 0; i <= SYNC_WORKLOAD; ++i) {
1969 /* 1967 /* select the one with lowest rb_key */
1970 * When priorities switched, we prefer starting 1968 queue = cfq_rb_first(service_tree_for(cfqg, prio, i));
1971 * from SYNC_NOIDLE (first choice), or just SYNC
1972 * over ASYNC
1973 */
1974 if (service_tree_for(cfqg, prio, cur_best, cfqd)->count)
1975 return cur_best;
1976 cur_best = SYNC_WORKLOAD;
1977 if (service_tree_for(cfqg, prio, cur_best, cfqd)->count)
1978 return cur_best;
1979
1980 return ASYNC_WORKLOAD;
1981 }
1982
1983 for (i = 0; i < 3; ++i) {
1984 /* otherwise, select the one with lowest rb_key */
1985 queue = cfq_rb_first(service_tree_for(cfqg, prio, i, cfqd));
1986 if (queue && 1969 if (queue &&
1987 (!key_valid || time_before(queue->rb_key, lowest_key))) { 1970 (!key_valid || time_before(queue->rb_key, lowest_key))) {
1988 lowest_key = queue->rb_key; 1971 lowest_key = queue->rb_key;
@@ -1996,8 +1979,6 @@ static enum wl_type_t cfq_choose_wl(struct cfq_data *cfqd,
1996 1979
1997static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg) 1980static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
1998{ 1981{
1999 enum wl_prio_t previous_prio = cfqd->serving_prio;
2000 bool prio_changed;
2001 unsigned slice; 1982 unsigned slice;
2002 unsigned count; 1983 unsigned count;
2003 struct cfq_rb_root *st; 1984 struct cfq_rb_root *st;
@@ -2025,24 +2006,19 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
2025 * (SYNC, SYNC_NOIDLE, ASYNC), and to compute a workload 2006 * (SYNC, SYNC_NOIDLE, ASYNC), and to compute a workload
2026 * expiration time 2007 * expiration time
2027 */ 2008 */
2028 prio_changed = (cfqd->serving_prio != previous_prio); 2009 st = service_tree_for(cfqg, cfqd->serving_prio, cfqd->serving_type);
2029 st = service_tree_for(cfqg, cfqd->serving_prio, cfqd->serving_type,
2030 cfqd);
2031 count = st->count; 2010 count = st->count;
2032 2011
2033 /* 2012 /*
2034 * If priority didn't change, check workload expiration, 2013 * check workload expiration, and that we still have other queues ready
2035 * and that we still have other queues ready
2036 */ 2014 */
2037 if (!prio_changed && count && 2015 if (count && !time_after(jiffies, cfqd->workload_expires))
2038 !time_after(jiffies, cfqd->workload_expires))
2039 return; 2016 return;
2040 2017
2041 /* otherwise select new workload type */ 2018 /* otherwise select new workload type */
2042 cfqd->serving_type = 2019 cfqd->serving_type =
2043 cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio, prio_changed); 2020 cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio);
2044 st = service_tree_for(cfqg, cfqd->serving_prio, cfqd->serving_type, 2021 st = service_tree_for(cfqg, cfqd->serving_prio, cfqd->serving_type);
2045 cfqd);
2046 count = st->count; 2022 count = st->count;
2047 2023
2048 /* 2024 /*