aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2009-12-03 12:59:55 -0500
committerJens Axboe <jens.axboe@oracle.com>2009-12-03 13:28:53 -0500
commitae30c286553c91c49af5cbc0265a05a6543d0c52 (patch)
tree1dcb055e156ca9190d0da5bccf32a3a166e12d52 /block/cfq-iosched.c
parentf26bd1f0a3a31bc5e16d285f5e1b00a56abf6238 (diff)
blkio: Implement group_isolation tunable
o If a group is running only a random reader, then it will not have enough traffic to keep disk busy and we will reduce overall throughput. This should result in better latencies for random reader though. If we don't idle on random reader service tree, then this random reader will experience large latencies if there are other groups present in system with sequential readers running in these. o One solution suggested by corrado is that by default keep the random readers or sync-noidle workload in root group so that during one dispatch round we idle only once on sync-noidle tree. This means that all the sync-idle workload queues will be in their respective group and we will see service differentiation in those but not on sync-noidle workload. o Provide a tunable group_isolation. If set, this will make sure that even sync-noidle queues go in their respective group and we wait on these. This provides stronger isolation between groups but at the expense of throughput if group does not have enough traffic to keep the disk busy. o By default group_isolation = 0 Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/cfq-iosched.c')
-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