aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index b9e483d9031e..063dcbb714e7 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -144,6 +144,7 @@ struct cfq_queue {
144 struct cfq_rb_root *service_tree; 144 struct cfq_rb_root *service_tree;
145 struct cfq_queue *new_cfqq; 145 struct cfq_queue *new_cfqq;
146 struct cfq_group *cfqg; 146 struct cfq_group *cfqg;
147 struct cfq_group *orig_cfqg;
147 /* Sectors dispatched in current dispatch round */ 148 /* Sectors dispatched in current dispatch round */
148 unsigned long nr_sectors; 149 unsigned long nr_sectors;
149}; 150};
@@ -273,6 +274,7 @@ struct cfq_data {
273 unsigned int cfq_slice_async_rq; 274 unsigned int cfq_slice_async_rq;
274 unsigned int cfq_slice_idle; 275 unsigned int cfq_slice_idle;
275 unsigned int cfq_latency; 276 unsigned int cfq_latency;
277 unsigned int cfq_group_isolation;
276 278
277 struct list_head cic_list; 279 struct list_head cic_list;
278 280
@@ -1120,6 +1122,33 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1120 struct cfq_rb_root *service_tree; 1122 struct cfq_rb_root *service_tree;
1121 int left; 1123 int left;
1122 int new_cfqq = 1; 1124 int new_cfqq = 1;
1125 int group_changed = 0;
1126
1127#ifdef CONFIG_CFQ_GROUP_IOSCHED
1128 if (!cfqd->cfq_group_isolation
1129 && cfqq_type(cfqq) == SYNC_NOIDLE_WORKLOAD
1130 && cfqq->cfqg && cfqq->cfqg != &cfqd->root_group) {
1131 /* Move this cfq to root group */
1132 cfq_log_cfqq(cfqd, cfqq, "moving to root group");
1133 if (!RB_EMPTY_NODE(&cfqq->rb_node))
1134 cfq_group_service_tree_del(cfqd, cfqq->cfqg);
1135 cfqq->orig_cfqg = cfqq->cfqg;
1136 cfqq->cfqg = &cfqd->root_group;
1137 atomic_inc(&cfqd->root_group.ref);
1138 group_changed = 1;
1139 } else if (!cfqd->cfq_group_isolation
1140 && cfqq_type(cfqq) == SYNC_WORKLOAD && cfqq->orig_cfqg) {
1141 /* cfqq is sequential now needs to go to its original group */
1142 BUG_ON(cfqq->cfqg != &cfqd->root_group);
1143 if (!RB_EMPTY_NODE(&cfqq->rb_node))
1144 cfq_group_service_tree_del(cfqd, cfqq->cfqg);
1145 cfq_put_cfqg(cfqq->cfqg);
1146 cfqq->cfqg = cfqq->orig_cfqg;
1147 cfqq->orig_cfqg = NULL;
1148 group_changed = 1;
1149 cfq_log_cfqq(cfqd, cfqq, "moved to origin group");
1150 }
1151#endif
1123 1152
1124 service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq), 1153 service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq),
1125 cfqq_type(cfqq), cfqd); 1154 cfqq_type(cfqq), cfqd);
@@ -1190,7 +1219,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1190 rb_link_node(&cfqq->rb_node, parent, p); 1219 rb_link_node(&cfqq->rb_node, parent, p);
1191 rb_insert_color(&cfqq->rb_node, &service_tree->rb); 1220 rb_insert_color(&cfqq->rb_node, &service_tree->rb);
1192 service_tree->count++; 1221 service_tree->count++;
1193 if (add_front || !new_cfqq) 1222 if ((add_front || !new_cfqq) && !group_changed)
1194 return; 1223 return;
1195 cfq_group_service_tree_add(cfqd, cfqq->cfqg); 1224 cfq_group_service_tree_add(cfqd, cfqq->cfqg);
1196} 1225}
@@ -2357,6 +2386,8 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
2357 BUG_ON(cfq_cfqq_on_rr(cfqq)); 2386 BUG_ON(cfq_cfqq_on_rr(cfqq));
2358 kmem_cache_free(cfq_pool, cfqq); 2387 kmem_cache_free(cfq_pool, cfqq);
2359 cfq_put_cfqg(cfqg); 2388 cfq_put_cfqg(cfqg);
2389 if (cfqq->orig_cfqg)
2390 cfq_put_cfqg(cfqq->orig_cfqg);
2360} 2391}
2361 2392
2362/* 2393/*
@@ -3670,6 +3701,7 @@ static void *cfq_init_queue(struct request_queue *q)
3670 cfqd->cfq_slice_async_rq = cfq_slice_async_rq; 3701 cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
3671 cfqd->cfq_slice_idle = cfq_slice_idle; 3702 cfqd->cfq_slice_idle = cfq_slice_idle;
3672 cfqd->cfq_latency = 1; 3703 cfqd->cfq_latency = 1;
3704 cfqd->cfq_group_isolation = 0;
3673 cfqd->hw_tag = -1; 3705 cfqd->hw_tag = -1;
3674 cfqd->last_end_sync_rq = jiffies; 3706 cfqd->last_end_sync_rq = jiffies;
3675 return cfqd; 3707 return cfqd;
@@ -3740,6 +3772,7 @@ SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
3740SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); 3772SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
3741SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); 3773SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
3742SHOW_FUNCTION(cfq_low_latency_show, cfqd->cfq_latency, 0); 3774SHOW_FUNCTION(cfq_low_latency_show, cfqd->cfq_latency, 0);
3775SHOW_FUNCTION(cfq_group_isolation_show, cfqd->cfq_group_isolation, 0);
3743#undef SHOW_FUNCTION 3776#undef SHOW_FUNCTION
3744 3777
3745#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ 3778#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
@@ -3772,6 +3805,7 @@ STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
3772STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, 3805STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1,
3773 UINT_MAX, 0); 3806 UINT_MAX, 0);
3774STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0); 3807STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0);
3808STORE_FUNCTION(cfq_group_isolation_store, &cfqd->cfq_group_isolation, 0, 1, 0);
3775#undef STORE_FUNCTION 3809#undef STORE_FUNCTION
3776 3810
3777#define CFQ_ATTR(name) \ 3811#define CFQ_ATTR(name) \
@@ -3788,6 +3822,7 @@ static struct elv_fs_entry cfq_attrs[] = {
3788 CFQ_ATTR(slice_async_rq), 3822 CFQ_ATTR(slice_async_rq),
3789 CFQ_ATTR(slice_idle), 3823 CFQ_ATTR(slice_idle),
3790 CFQ_ATTR(low_latency), 3824 CFQ_ATTR(low_latency),
3825 CFQ_ATTR(group_isolation),
3791 __ATTR_NULL 3826 __ATTR_NULL
3792}; 3827};
3793 3828