aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c112
1 files changed, 58 insertions, 54 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 78ee4b1d4e85..8427697c5437 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -87,7 +87,6 @@ struct cfq_rb_root {
87 unsigned count; 87 unsigned count;
88 unsigned total_weight; 88 unsigned total_weight;
89 u64 min_vdisktime; 89 u64 min_vdisktime;
90 struct rb_node *active;
91}; 90};
92#define CFQ_RB_ROOT (struct cfq_rb_root) { .rb = RB_ROOT, .left = NULL, \ 91#define CFQ_RB_ROOT (struct cfq_rb_root) { .rb = RB_ROOT, .left = NULL, \
93 .count = 0, .min_vdisktime = 0, } 92 .count = 0, .min_vdisktime = 0, }
@@ -97,7 +96,7 @@ struct cfq_rb_root {
97 */ 96 */
98struct cfq_queue { 97struct cfq_queue {
99 /* reference count */ 98 /* reference count */
100 atomic_t ref; 99 int ref;
101 /* various state flags, see below */ 100 /* various state flags, see below */
102 unsigned int flags; 101 unsigned int flags;
103 /* parent cfq_data */ 102 /* parent cfq_data */
@@ -180,7 +179,6 @@ struct cfq_group {
180 /* group service_tree key */ 179 /* group service_tree key */
181 u64 vdisktime; 180 u64 vdisktime;
182 unsigned int weight; 181 unsigned int weight;
183 bool on_st;
184 182
185 /* number of cfqq currently on this group */ 183 /* number of cfqq currently on this group */
186 int nr_cfqq; 184 int nr_cfqq;
@@ -209,7 +207,7 @@ struct cfq_group {
209 struct blkio_group blkg; 207 struct blkio_group blkg;
210#ifdef CONFIG_CFQ_GROUP_IOSCHED 208#ifdef CONFIG_CFQ_GROUP_IOSCHED
211 struct hlist_node cfqd_node; 209 struct hlist_node cfqd_node;
212 atomic_t ref; 210 int ref;
213#endif 211#endif
214 /* number of requests that are on the dispatch list or inside driver */ 212 /* number of requests that are on the dispatch list or inside driver */
215 int dispatched; 213 int dispatched;
@@ -563,11 +561,6 @@ static void update_min_vdisktime(struct cfq_rb_root *st)
563 u64 vdisktime = st->min_vdisktime; 561 u64 vdisktime = st->min_vdisktime;
564 struct cfq_group *cfqg; 562 struct cfq_group *cfqg;
565 563
566 if (st->active) {
567 cfqg = rb_entry_cfqg(st->active);
568 vdisktime = cfqg->vdisktime;
569 }
570
571 if (st->left) { 564 if (st->left) {
572 cfqg = rb_entry_cfqg(st->left); 565 cfqg = rb_entry_cfqg(st->left);
573 vdisktime = min_vdisktime(vdisktime, cfqg->vdisktime); 566 vdisktime = min_vdisktime(vdisktime, cfqg->vdisktime);
@@ -646,11 +639,11 @@ cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
646static inline bool cfq_slice_used(struct cfq_queue *cfqq) 639static inline bool cfq_slice_used(struct cfq_queue *cfqq)
647{ 640{
648 if (cfq_cfqq_slice_new(cfqq)) 641 if (cfq_cfqq_slice_new(cfqq))
649 return 0; 642 return false;
650 if (time_before(jiffies, cfqq->slice_end)) 643 if (time_before(jiffies, cfqq->slice_end))
651 return 0; 644 return false;
652 645
653 return 1; 646 return true;
654} 647}
655 648
656/* 649/*
@@ -869,7 +862,7 @@ cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
869 struct rb_node *n; 862 struct rb_node *n;
870 863
871 cfqg->nr_cfqq++; 864 cfqg->nr_cfqq++;
872 if (cfqg->on_st) 865 if (!RB_EMPTY_NODE(&cfqg->rb_node))
873 return; 866 return;
874 867
875 /* 868 /*
@@ -885,7 +878,6 @@ cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
885 cfqg->vdisktime = st->min_vdisktime; 878 cfqg->vdisktime = st->min_vdisktime;
886 879
887 __cfq_group_service_tree_add(st, cfqg); 880 __cfq_group_service_tree_add(st, cfqg);
888 cfqg->on_st = true;
889 st->total_weight += cfqg->weight; 881 st->total_weight += cfqg->weight;
890} 882}
891 883
@@ -894,9 +886,6 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
894{ 886{
895 struct cfq_rb_root *st = &cfqd->grp_service_tree; 887 struct cfq_rb_root *st = &cfqd->grp_service_tree;
896 888
897 if (st->active == &cfqg->rb_node)
898 st->active = NULL;
899
900 BUG_ON(cfqg->nr_cfqq < 1); 889 BUG_ON(cfqg->nr_cfqq < 1);
901 cfqg->nr_cfqq--; 890 cfqg->nr_cfqq--;
902 891
@@ -905,7 +894,6 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
905 return; 894 return;
906 895
907 cfq_log_cfqg(cfqd, cfqg, "del_from_rr group"); 896 cfq_log_cfqg(cfqd, cfqg, "del_from_rr group");
908 cfqg->on_st = false;
909 st->total_weight -= cfqg->weight; 897 st->total_weight -= cfqg->weight;
910 if (!RB_EMPTY_NODE(&cfqg->rb_node)) 898 if (!RB_EMPTY_NODE(&cfqg->rb_node))
911 cfq_rb_erase(&cfqg->rb_node, st); 899 cfq_rb_erase(&cfqg->rb_node, st);
@@ -1026,7 +1014,7 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
1026 * elevator which will be dropped by either elevator exit 1014 * elevator which will be dropped by either elevator exit
1027 * or cgroup deletion path depending on who is exiting first. 1015 * or cgroup deletion path depending on who is exiting first.
1028 */ 1016 */
1029 atomic_set(&cfqg->ref, 1); 1017 cfqg->ref = 1;
1030 1018
1031 /* 1019 /*
1032 * Add group onto cgroup list. It might happen that bdi->dev is 1020 * Add group onto cgroup list. It might happen that bdi->dev is
@@ -1071,7 +1059,7 @@ static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create)
1071 1059
1072static inline struct cfq_group *cfq_ref_get_cfqg(struct cfq_group *cfqg) 1060static inline struct cfq_group *cfq_ref_get_cfqg(struct cfq_group *cfqg)
1073{ 1061{
1074 atomic_inc(&cfqg->ref); 1062 cfqg->ref++;
1075 return cfqg; 1063 return cfqg;
1076} 1064}
1077 1065
@@ -1083,7 +1071,7 @@ static void cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg)
1083 1071
1084 cfqq->cfqg = cfqg; 1072 cfqq->cfqg = cfqg;
1085 /* cfqq reference on cfqg */ 1073 /* cfqq reference on cfqg */
1086 atomic_inc(&cfqq->cfqg->ref); 1074 cfqq->cfqg->ref++;
1087} 1075}
1088 1076
1089static void cfq_put_cfqg(struct cfq_group *cfqg) 1077static void cfq_put_cfqg(struct cfq_group *cfqg)
@@ -1091,11 +1079,12 @@ static void cfq_put_cfqg(struct cfq_group *cfqg)
1091 struct cfq_rb_root *st; 1079 struct cfq_rb_root *st;
1092 int i, j; 1080 int i, j;
1093 1081
1094 BUG_ON(atomic_read(&cfqg->ref) <= 0); 1082 BUG_ON(cfqg->ref <= 0);
1095 if (!atomic_dec_and_test(&cfqg->ref)) 1083 cfqg->ref--;
1084 if (cfqg->ref)
1096 return; 1085 return;
1097 for_each_cfqg_st(cfqg, i, j, st) 1086 for_each_cfqg_st(cfqg, i, j, st)
1098 BUG_ON(!RB_EMPTY_ROOT(&st->rb) || st->active != NULL); 1087 BUG_ON(!RB_EMPTY_ROOT(&st->rb));
1099 kfree(cfqg); 1088 kfree(cfqg);
1100} 1089}
1101 1090
@@ -1200,7 +1189,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1200 cfq_group_service_tree_del(cfqd, cfqq->cfqg); 1189 cfq_group_service_tree_del(cfqd, cfqq->cfqg);
1201 cfqq->orig_cfqg = cfqq->cfqg; 1190 cfqq->orig_cfqg = cfqq->cfqg;
1202 cfqq->cfqg = &cfqd->root_group; 1191 cfqq->cfqg = &cfqd->root_group;
1203 atomic_inc(&cfqd->root_group.ref); 1192 cfqd->root_group.ref++;
1204 group_changed = 1; 1193 group_changed = 1;
1205 } else if (!cfqd->cfq_group_isolation 1194 } else if (!cfqd->cfq_group_isolation
1206 && cfqq_type(cfqq) == SYNC_WORKLOAD && cfqq->orig_cfqg) { 1195 && cfqq_type(cfqq) == SYNC_WORKLOAD && cfqq->orig_cfqg) {
@@ -1687,9 +1676,6 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1687 if (cfqq == cfqd->active_queue) 1676 if (cfqq == cfqd->active_queue)
1688 cfqd->active_queue = NULL; 1677 cfqd->active_queue = NULL;
1689 1678
1690 if (&cfqq->cfqg->rb_node == cfqd->grp_service_tree.active)
1691 cfqd->grp_service_tree.active = NULL;
1692
1693 if (cfqd->active_cic) { 1679 if (cfqd->active_cic) {
1694 put_io_context(cfqd->active_cic->ioc); 1680 put_io_context(cfqd->active_cic->ioc);
1695 cfqd->active_cic = NULL; 1681 cfqd->active_cic = NULL;
@@ -1901,10 +1887,10 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1901 * in their service tree. 1887 * in their service tree.
1902 */ 1888 */
1903 if (service_tree->count == 1 && cfq_cfqq_sync(cfqq)) 1889 if (service_tree->count == 1 && cfq_cfqq_sync(cfqq))
1904 return 1; 1890 return true;
1905 cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d", 1891 cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d",
1906 service_tree->count); 1892 service_tree->count);
1907 return 0; 1893 return false;
1908} 1894}
1909 1895
1910static void cfq_arm_slice_timer(struct cfq_data *cfqd) 1896static void cfq_arm_slice_timer(struct cfq_data *cfqd)
@@ -2040,7 +2026,7 @@ static int cfqq_process_refs(struct cfq_queue *cfqq)
2040 int process_refs, io_refs; 2026 int process_refs, io_refs;
2041 2027
2042 io_refs = cfqq->allocated[READ] + cfqq->allocated[WRITE]; 2028 io_refs = cfqq->allocated[READ] + cfqq->allocated[WRITE];
2043 process_refs = atomic_read(&cfqq->ref) - io_refs; 2029 process_refs = cfqq->ref - io_refs;
2044 BUG_ON(process_refs < 0); 2030 BUG_ON(process_refs < 0);
2045 return process_refs; 2031 return process_refs;
2046} 2032}
@@ -2080,10 +2066,10 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq)
2080 */ 2066 */
2081 if (new_process_refs >= process_refs) { 2067 if (new_process_refs >= process_refs) {
2082 cfqq->new_cfqq = new_cfqq; 2068 cfqq->new_cfqq = new_cfqq;
2083 atomic_add(process_refs, &new_cfqq->ref); 2069 new_cfqq->ref += process_refs;
2084 } else { 2070 } else {
2085 new_cfqq->new_cfqq = cfqq; 2071 new_cfqq->new_cfqq = cfqq;
2086 atomic_add(new_process_refs, &cfqq->ref); 2072 cfqq->ref += new_process_refs;
2087 } 2073 }
2088} 2074}
2089 2075
@@ -2116,12 +2102,7 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
2116 unsigned count; 2102 unsigned count;
2117 struct cfq_rb_root *st; 2103 struct cfq_rb_root *st;
2118 unsigned group_slice; 2104 unsigned group_slice;
2119 2105 enum wl_prio_t original_prio = cfqd->serving_prio;
2120 if (!cfqg) {
2121 cfqd->serving_prio = IDLE_WORKLOAD;
2122 cfqd->workload_expires = jiffies + 1;
2123 return;
2124 }
2125 2106
2126 /* Choose next priority. RT > BE > IDLE */ 2107 /* Choose next priority. RT > BE > IDLE */
2127 if (cfq_group_busy_queues_wl(RT_WORKLOAD, cfqd, cfqg)) 2108 if (cfq_group_busy_queues_wl(RT_WORKLOAD, cfqd, cfqg))
@@ -2134,6 +2115,9 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
2134 return; 2115 return;
2135 } 2116 }
2136 2117
2118 if (original_prio != cfqd->serving_prio)
2119 goto new_workload;
2120
2137 /* 2121 /*
2138 * For RT and BE, we have to choose also the type 2122 * For RT and BE, we have to choose also the type
2139 * (SYNC, SYNC_NOIDLE, ASYNC), and to compute a workload 2123 * (SYNC, SYNC_NOIDLE, ASYNC), and to compute a workload
@@ -2148,6 +2132,7 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
2148 if (count && !time_after(jiffies, cfqd->workload_expires)) 2132 if (count && !time_after(jiffies, cfqd->workload_expires))
2149 return; 2133 return;
2150 2134
2135new_workload:
2151 /* otherwise select new workload type */ 2136 /* otherwise select new workload type */
2152 cfqd->serving_type = 2137 cfqd->serving_type =
2153 cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio); 2138 cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio);
@@ -2199,7 +2184,6 @@ static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd)
2199 if (RB_EMPTY_ROOT(&st->rb)) 2184 if (RB_EMPTY_ROOT(&st->rb))
2200 return NULL; 2185 return NULL;
2201 cfqg = cfq_rb_first_group(st); 2186 cfqg = cfq_rb_first_group(st);
2202 st->active = &cfqg->rb_node;
2203 update_min_vdisktime(st); 2187 update_min_vdisktime(st);
2204 return cfqg; 2188 return cfqg;
2205} 2189}
@@ -2293,6 +2277,17 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
2293 goto keep_queue; 2277 goto keep_queue;
2294 } 2278 }
2295 2279
2280 /*
2281 * This is a deep seek queue, but the device is much faster than
2282 * the queue can deliver, don't idle
2283 **/
2284 if (CFQQ_SEEKY(cfqq) && cfq_cfqq_idle_window(cfqq) &&
2285 (cfq_cfqq_slice_new(cfqq) ||
2286 (cfqq->slice_end - jiffies > jiffies - cfqq->slice_start))) {
2287 cfq_clear_cfqq_deep(cfqq);
2288 cfq_clear_cfqq_idle_window(cfqq);
2289 }
2290
2296 if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) { 2291 if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) {
2297 cfqq = NULL; 2292 cfqq = NULL;
2298 goto keep_queue; 2293 goto keep_queue;
@@ -2367,12 +2362,12 @@ static inline bool cfq_slice_used_soon(struct cfq_data *cfqd,
2367{ 2362{
2368 /* the queue hasn't finished any request, can't estimate */ 2363 /* the queue hasn't finished any request, can't estimate */
2369 if (cfq_cfqq_slice_new(cfqq)) 2364 if (cfq_cfqq_slice_new(cfqq))
2370 return 1; 2365 return true;
2371 if (time_after(jiffies + cfqd->cfq_slice_idle * cfqq->dispatched, 2366 if (time_after(jiffies + cfqd->cfq_slice_idle * cfqq->dispatched,
2372 cfqq->slice_end)) 2367 cfqq->slice_end))
2373 return 1; 2368 return true;
2374 2369
2375 return 0; 2370 return false;
2376} 2371}
2377 2372
2378static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq) 2373static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq)
@@ -2538,9 +2533,10 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
2538 struct cfq_data *cfqd = cfqq->cfqd; 2533 struct cfq_data *cfqd = cfqq->cfqd;
2539 struct cfq_group *cfqg, *orig_cfqg; 2534 struct cfq_group *cfqg, *orig_cfqg;
2540 2535
2541 BUG_ON(atomic_read(&cfqq->ref) <= 0); 2536 BUG_ON(cfqq->ref <= 0);
2542 2537
2543 if (!atomic_dec_and_test(&cfqq->ref)) 2538 cfqq->ref--;
2539 if (cfqq->ref)
2544 return; 2540 return;
2545 2541
2546 cfq_log_cfqq(cfqd, cfqq, "put_queue"); 2542 cfq_log_cfqq(cfqd, cfqq, "put_queue");
@@ -2843,7 +2839,7 @@ static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
2843 RB_CLEAR_NODE(&cfqq->p_node); 2839 RB_CLEAR_NODE(&cfqq->p_node);
2844 INIT_LIST_HEAD(&cfqq->fifo); 2840 INIT_LIST_HEAD(&cfqq->fifo);
2845 2841
2846 atomic_set(&cfqq->ref, 0); 2842 cfqq->ref = 0;
2847 cfqq->cfqd = cfqd; 2843 cfqq->cfqd = cfqd;
2848 2844
2849 cfq_mark_cfqq_prio_changed(cfqq); 2845 cfq_mark_cfqq_prio_changed(cfqq);
@@ -2979,11 +2975,11 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct io_context *ioc,
2979 * pin the queue now that it's allocated, scheduler exit will prune it 2975 * pin the queue now that it's allocated, scheduler exit will prune it
2980 */ 2976 */
2981 if (!is_sync && !(*async_cfqq)) { 2977 if (!is_sync && !(*async_cfqq)) {
2982 atomic_inc(&cfqq->ref); 2978 cfqq->ref++;
2983 *async_cfqq = cfqq; 2979 *async_cfqq = cfqq;
2984 } 2980 }
2985 2981
2986 atomic_inc(&cfqq->ref); 2982 cfqq->ref++;
2987 return cfqq; 2983 return cfqq;
2988} 2984}
2989 2985
@@ -3265,6 +3261,10 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
3265 if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq)) 3261 if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
3266 return true; 3262 return true;
3267 3263
3264 /* An idle queue should not be idle now for some reason */
3265 if (RB_EMPTY_ROOT(&cfqq->sort_list) && !cfq_should_idle(cfqd, cfqq))
3266 return true;
3267
3268 if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq)) 3268 if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
3269 return false; 3269 return false;
3270 3270
@@ -3681,13 +3681,13 @@ new_queue:
3681 } 3681 }
3682 3682
3683 cfqq->allocated[rw]++; 3683 cfqq->allocated[rw]++;
3684 atomic_inc(&cfqq->ref); 3684 cfqq->ref++;
3685
3686 spin_unlock_irqrestore(q->queue_lock, flags);
3687
3688 rq->elevator_private = cic; 3685 rq->elevator_private = cic;
3689 rq->elevator_private2 = cfqq; 3686 rq->elevator_private2 = cfqq;
3690 rq->elevator_private3 = cfq_ref_get_cfqg(cfqq->cfqg); 3687 rq->elevator_private3 = cfq_ref_get_cfqg(cfqq->cfqg);
3688
3689 spin_unlock_irqrestore(q->queue_lock, flags);
3690
3691 return 0; 3691 return 0;
3692 3692
3693queue_fail: 3693queue_fail:
@@ -3862,6 +3862,10 @@ static void *cfq_init_queue(struct request_queue *q)
3862 if (!cfqd) 3862 if (!cfqd)
3863 return NULL; 3863 return NULL;
3864 3864
3865 /*
3866 * Don't need take queue_lock in the routine, since we are
3867 * initializing the ioscheduler, and nobody is using cfqd
3868 */
3865 cfqd->cic_index = i; 3869 cfqd->cic_index = i;
3866 3870
3867 /* Init root service tree */ 3871 /* Init root service tree */
@@ -3881,7 +3885,7 @@ static void *cfq_init_queue(struct request_queue *q)
3881 * Take a reference to root group which we never drop. This is just 3885 * Take a reference to root group which we never drop. This is just
3882 * to make sure that cfq_put_cfqg() does not try to kfree root group 3886 * to make sure that cfq_put_cfqg() does not try to kfree root group
3883 */ 3887 */
3884 atomic_set(&cfqg->ref, 1); 3888 cfqg->ref = 1;
3885 rcu_read_lock(); 3889 rcu_read_lock();
3886 cfq_blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, 3890 cfq_blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg,
3887 (void *)cfqd, 0); 3891 (void *)cfqd, 0);
@@ -3901,7 +3905,7 @@ static void *cfq_init_queue(struct request_queue *q)
3901 * will not attempt to free it. 3905 * will not attempt to free it.
3902 */ 3906 */
3903 cfq_init_cfqq(cfqd, &cfqd->oom_cfqq, 1, 0); 3907 cfq_init_cfqq(cfqd, &cfqd->oom_cfqq, 1, 0);
3904 atomic_inc(&cfqd->oom_cfqq.ref); 3908 cfqd->oom_cfqq.ref++;
3905 cfq_link_cfqq_cfqg(&cfqd->oom_cfqq, &cfqd->root_group); 3909 cfq_link_cfqq_cfqg(&cfqd->oom_cfqq, &cfqd->root_group);
3906 3910
3907 INIT_LIST_HEAD(&cfqd->cic_list); 3911 INIT_LIST_HEAD(&cfqd->cic_list);