summaryrefslogtreecommitdiffstats
path: root/block/bfq-cgroup.c
diff options
context:
space:
mode:
authorLuca Miccio <lucmiccio@gmail.com>2017-11-13 01:34:10 -0500
committerJens Axboe <axboe@kernel.dk>2017-11-14 22:13:33 -0500
commita33801e8b4735b8d473f963e5854172f9cde3e8b (patch)
treeacebf1dbfbe5effb178f76d31b841b9fb24f45fd /block/bfq-cgroup.c
parent24bfd19bb7890255693ee5cb6dc100d8d215d00b (diff)
block, bfq: move debug blkio stats behind CONFIG_DEBUG_BLK_CGROUP
BFQ currently creates, and updates, its own instance of the whole set of blkio statistics that cfq creates. Yet, from the comments of Tejun Heo in [1], it turned out that most of these statistics are meant/useful only for debugging. This commit makes BFQ create the latter, debugging statistics only if the option CONFIG_DEBUG_BLK_CGROUP is set. By doing so, this commit also enables BFQ to enjoy a high perfomance boost. The reason is that, if CONFIG_DEBUG_BLK_CGROUP is not set, then BFQ has to update far fewer statistics, and, in particular, not the heaviest to update. To give an idea of the benefits, if CONFIG_DEBUG_BLK_CGROUP is not set, then, on an Intel i7-4850HQ, and with 8 threads doing random I/O in parallel on null_blk (configured with 0 latency), the throughput of BFQ grows from 310 to 400 KIOPS (+30%). We have measured similar or even much higher boosts with other CPUs: e.g., +45% with an ARM CortexTM-A53 Octa-core. Our results have been obtained and can be reproduced very easily with the script in [1]. [1] https://www.spinics.net/lists/linux-block/msg18943.html Suggested-by: Tejun Heo <tj@kernel.org> Suggested-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Lee Tibbert <lee.tibbert@gmail.com> Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name> Signed-off-by: Luca Miccio <lucmiccio@gmail.com> Signed-off-by: Paolo Valente <paolo.valente@linaro.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/bfq-cgroup.c')
-rw-r--r--block/bfq-cgroup.c148
1 files changed, 84 insertions, 64 deletions
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index ceefb9a706d6..da1525ec4c87 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -24,7 +24,7 @@
24 24
25#include "bfq-iosched.h" 25#include "bfq-iosched.h"
26 26
27#ifdef CONFIG_BFQ_GROUP_IOSCHED 27#if defined(CONFIG_BFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP)
28 28
29/* bfqg stats flags */ 29/* bfqg stats flags */
30enum bfqg_stats_flags { 30enum bfqg_stats_flags {
@@ -152,6 +152,57 @@ void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg)
152 bfqg_stats_update_group_wait_time(stats); 152 bfqg_stats_update_group_wait_time(stats);
153} 153}
154 154
155void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
156 unsigned int op)
157{
158 blkg_rwstat_add(&bfqg->stats.queued, op, 1);
159 bfqg_stats_end_empty_time(&bfqg->stats);
160 if (!(bfqq == ((struct bfq_data *)bfqg->bfqd)->in_service_queue))
161 bfqg_stats_set_start_group_wait_time(bfqg, bfqq_group(bfqq));
162}
163
164void bfqg_stats_update_io_remove(struct bfq_group *bfqg, unsigned int op)
165{
166 blkg_rwstat_add(&bfqg->stats.queued, op, -1);
167}
168
169void bfqg_stats_update_io_merged(struct bfq_group *bfqg, unsigned int op)
170{
171 blkg_rwstat_add(&bfqg->stats.merged, op, 1);
172}
173
174void bfqg_stats_update_completion(struct bfq_group *bfqg, uint64_t start_time,
175 uint64_t io_start_time, unsigned int op)
176{
177 struct bfqg_stats *stats = &bfqg->stats;
178 unsigned long long now = sched_clock();
179
180 if (time_after64(now, io_start_time))
181 blkg_rwstat_add(&stats->service_time, op,
182 now - io_start_time);
183 if (time_after64(io_start_time, start_time))
184 blkg_rwstat_add(&stats->wait_time, op,
185 io_start_time - start_time);
186}
187
188#else /* CONFIG_BFQ_GROUP_IOSCHED && CONFIG_DEBUG_BLK_CGROUP */
189
190void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
191 unsigned int op) { }
192void bfqg_stats_update_io_remove(struct bfq_group *bfqg, unsigned int op) { }
193void bfqg_stats_update_io_merged(struct bfq_group *bfqg, unsigned int op) { }
194void bfqg_stats_update_completion(struct bfq_group *bfqg, uint64_t start_time,
195 uint64_t io_start_time, unsigned int op) { }
196void bfqg_stats_update_dequeue(struct bfq_group *bfqg) { }
197void bfqg_stats_set_start_empty_time(struct bfq_group *bfqg) { }
198void bfqg_stats_update_idle_time(struct bfq_group *bfqg) { }
199void bfqg_stats_set_start_idle_time(struct bfq_group *bfqg) { }
200void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg) { }
201
202#endif /* CONFIG_BFQ_GROUP_IOSCHED && CONFIG_DEBUG_BLK_CGROUP */
203
204#ifdef CONFIG_BFQ_GROUP_IOSCHED
205
155/* 206/*
156 * blk-cgroup policy-related handlers 207 * blk-cgroup policy-related handlers
157 * The following functions help in converting between blk-cgroup 208 * The following functions help in converting between blk-cgroup
@@ -229,42 +280,10 @@ void bfqg_and_blkg_put(struct bfq_group *bfqg)
229 blkg_put(bfqg_to_blkg(bfqg)); 280 blkg_put(bfqg_to_blkg(bfqg));
230} 281}
231 282
232void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
233 unsigned int op)
234{
235 blkg_rwstat_add(&bfqg->stats.queued, op, 1);
236 bfqg_stats_end_empty_time(&bfqg->stats);
237 if (!(bfqq == ((struct bfq_data *)bfqg->bfqd)->in_service_queue))
238 bfqg_stats_set_start_group_wait_time(bfqg, bfqq_group(bfqq));
239}
240
241void bfqg_stats_update_io_remove(struct bfq_group *bfqg, unsigned int op)
242{
243 blkg_rwstat_add(&bfqg->stats.queued, op, -1);
244}
245
246void bfqg_stats_update_io_merged(struct bfq_group *bfqg, unsigned int op)
247{
248 blkg_rwstat_add(&bfqg->stats.merged, op, 1);
249}
250
251void bfqg_stats_update_completion(struct bfq_group *bfqg, uint64_t start_time,
252 uint64_t io_start_time, unsigned int op)
253{
254 struct bfqg_stats *stats = &bfqg->stats;
255 unsigned long long now = sched_clock();
256
257 if (time_after64(now, io_start_time))
258 blkg_rwstat_add(&stats->service_time, op,
259 now - io_start_time);
260 if (time_after64(io_start_time, start_time))
261 blkg_rwstat_add(&stats->wait_time, op,
262 io_start_time - start_time);
263}
264
265/* @stats = 0 */ 283/* @stats = 0 */
266static void bfqg_stats_reset(struct bfqg_stats *stats) 284static void bfqg_stats_reset(struct bfqg_stats *stats)
267{ 285{
286#ifdef CONFIG_DEBUG_BLK_CGROUP
268 /* queued stats shouldn't be cleared */ 287 /* queued stats shouldn't be cleared */
269 blkg_rwstat_reset(&stats->merged); 288 blkg_rwstat_reset(&stats->merged);
270 blkg_rwstat_reset(&stats->service_time); 289 blkg_rwstat_reset(&stats->service_time);
@@ -276,6 +295,7 @@ static void bfqg_stats_reset(struct bfqg_stats *stats)
276 blkg_stat_reset(&stats->group_wait_time); 295 blkg_stat_reset(&stats->group_wait_time);
277 blkg_stat_reset(&stats->idle_time); 296 blkg_stat_reset(&stats->idle_time);
278 blkg_stat_reset(&stats->empty_time); 297 blkg_stat_reset(&stats->empty_time);
298#endif
279} 299}
280 300
281/* @to += @from */ 301/* @to += @from */
@@ -284,6 +304,7 @@ static void bfqg_stats_add_aux(struct bfqg_stats *to, struct bfqg_stats *from)
284 if (!to || !from) 304 if (!to || !from)
285 return; 305 return;
286 306
307#ifdef CONFIG_DEBUG_BLK_CGROUP
287 /* queued stats shouldn't be cleared */ 308 /* queued stats shouldn't be cleared */
288 blkg_rwstat_add_aux(&to->merged, &from->merged); 309 blkg_rwstat_add_aux(&to->merged, &from->merged);
289 blkg_rwstat_add_aux(&to->service_time, &from->service_time); 310 blkg_rwstat_add_aux(&to->service_time, &from->service_time);
@@ -296,6 +317,7 @@ static void bfqg_stats_add_aux(struct bfqg_stats *to, struct bfqg_stats *from)
296 blkg_stat_add_aux(&to->group_wait_time, &from->group_wait_time); 317 blkg_stat_add_aux(&to->group_wait_time, &from->group_wait_time);
297 blkg_stat_add_aux(&to->idle_time, &from->idle_time); 318 blkg_stat_add_aux(&to->idle_time, &from->idle_time);
298 blkg_stat_add_aux(&to->empty_time, &from->empty_time); 319 blkg_stat_add_aux(&to->empty_time, &from->empty_time);
320#endif
299} 321}
300 322
301/* 323/*
@@ -342,6 +364,7 @@ void bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg)
342 364
343static void bfqg_stats_exit(struct bfqg_stats *stats) 365static void bfqg_stats_exit(struct bfqg_stats *stats)
344{ 366{
367#ifdef CONFIG_DEBUG_BLK_CGROUP
345 blkg_rwstat_exit(&stats->merged); 368 blkg_rwstat_exit(&stats->merged);
346 blkg_rwstat_exit(&stats->service_time); 369 blkg_rwstat_exit(&stats->service_time);
347 blkg_rwstat_exit(&stats->wait_time); 370 blkg_rwstat_exit(&stats->wait_time);
@@ -353,10 +376,12 @@ static void bfqg_stats_exit(struct bfqg_stats *stats)
353 blkg_stat_exit(&stats->group_wait_time); 376 blkg_stat_exit(&stats->group_wait_time);
354 blkg_stat_exit(&stats->idle_time); 377 blkg_stat_exit(&stats->idle_time);
355 blkg_stat_exit(&stats->empty_time); 378 blkg_stat_exit(&stats->empty_time);
379#endif
356} 380}
357 381
358static int bfqg_stats_init(struct bfqg_stats *stats, gfp_t gfp) 382static int bfqg_stats_init(struct bfqg_stats *stats, gfp_t gfp)
359{ 383{
384#ifdef CONFIG_DEBUG_BLK_CGROUP
360 if (blkg_rwstat_init(&stats->merged, gfp) || 385 if (blkg_rwstat_init(&stats->merged, gfp) ||
361 blkg_rwstat_init(&stats->service_time, gfp) || 386 blkg_rwstat_init(&stats->service_time, gfp) ||
362 blkg_rwstat_init(&stats->wait_time, gfp) || 387 blkg_rwstat_init(&stats->wait_time, gfp) ||
@@ -371,6 +396,7 @@ static int bfqg_stats_init(struct bfqg_stats *stats, gfp_t gfp)
371 bfqg_stats_exit(stats); 396 bfqg_stats_exit(stats);
372 return -ENOMEM; 397 return -ENOMEM;
373 } 398 }
399#endif
374 400
375 return 0; 401 return 0;
376} 402}
@@ -887,6 +913,7 @@ static ssize_t bfq_io_set_weight(struct kernfs_open_file *of,
887 return bfq_io_set_weight_legacy(of_css(of), NULL, weight); 913 return bfq_io_set_weight_legacy(of_css(of), NULL, weight);
888} 914}
889 915
916#ifdef CONFIG_DEBUG_BLK_CGROUP
890static int bfqg_print_stat(struct seq_file *sf, void *v) 917static int bfqg_print_stat(struct seq_file *sf, void *v)
891{ 918{
892 blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), blkg_prfill_stat, 919 blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), blkg_prfill_stat,
@@ -991,6 +1018,7 @@ static int bfqg_print_avg_queue_size(struct seq_file *sf, void *v)
991 0, false); 1018 0, false);
992 return 0; 1019 return 0;
993} 1020}
1021#endif /* CONFIG_DEBUG_BLK_CGROUP */
994 1022
995struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node) 1023struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node)
996{ 1024{
@@ -1029,15 +1057,6 @@ struct cftype bfq_blkcg_legacy_files[] = {
1029 1057
1030 /* statistics, covers only the tasks in the bfqg */ 1058 /* statistics, covers only the tasks in the bfqg */
1031 { 1059 {
1032 .name = "bfq.time",
1033 .private = offsetof(struct bfq_group, stats.time),
1034 .seq_show = bfqg_print_stat,
1035 },
1036 {
1037 .name = "bfq.sectors",
1038 .seq_show = bfqg_print_stat_sectors,
1039 },
1040 {
1041 .name = "bfq.io_service_bytes", 1060 .name = "bfq.io_service_bytes",
1042 .private = (unsigned long)&blkcg_policy_bfq, 1061 .private = (unsigned long)&blkcg_policy_bfq,
1043 .seq_show = blkg_print_stat_bytes, 1062 .seq_show = blkg_print_stat_bytes,
@@ -1047,6 +1066,16 @@ struct cftype bfq_blkcg_legacy_files[] = {
1047 .private = (unsigned long)&blkcg_policy_bfq, 1066 .private = (unsigned long)&blkcg_policy_bfq,
1048 .seq_show = blkg_print_stat_ios, 1067 .seq_show = blkg_print_stat_ios,
1049 }, 1068 },
1069#ifdef CONFIG_DEBUG_BLK_CGROUP
1070 {
1071 .name = "bfq.time",
1072 .private = offsetof(struct bfq_group, stats.time),
1073 .seq_show = bfqg_print_stat,
1074 },
1075 {
1076 .name = "bfq.sectors",
1077 .seq_show = bfqg_print_stat_sectors,
1078 },
1050 { 1079 {
1051 .name = "bfq.io_service_time", 1080 .name = "bfq.io_service_time",
1052 .private = offsetof(struct bfq_group, stats.service_time), 1081 .private = offsetof(struct bfq_group, stats.service_time),
@@ -1067,18 +1096,10 @@ struct cftype bfq_blkcg_legacy_files[] = {
1067 .private = offsetof(struct bfq_group, stats.queued), 1096 .private = offsetof(struct bfq_group, stats.queued),
1068 .seq_show = bfqg_print_rwstat, 1097 .seq_show = bfqg_print_rwstat,
1069 }, 1098 },
1099#endif /* CONFIG_DEBUG_BLK_CGROUP */
1070 1100
1071 /* the same statictics which cover the bfqg and its descendants */ 1101 /* the same statictics which cover the bfqg and its descendants */
1072 { 1102 {
1073 .name = "bfq.time_recursive",
1074 .private = offsetof(struct bfq_group, stats.time),
1075 .seq_show = bfqg_print_stat_recursive,
1076 },
1077 {
1078 .name = "bfq.sectors_recursive",
1079 .seq_show = bfqg_print_stat_sectors_recursive,
1080 },
1081 {
1082 .name = "bfq.io_service_bytes_recursive", 1103 .name = "bfq.io_service_bytes_recursive",
1083 .private = (unsigned long)&blkcg_policy_bfq, 1104 .private = (unsigned long)&blkcg_policy_bfq,
1084 .seq_show = blkg_print_stat_bytes_recursive, 1105 .seq_show = blkg_print_stat_bytes_recursive,
@@ -1088,6 +1109,16 @@ struct cftype bfq_blkcg_legacy_files[] = {
1088 .private = (unsigned long)&blkcg_policy_bfq, 1109 .private = (unsigned long)&blkcg_policy_bfq,
1089 .seq_show = blkg_print_stat_ios_recursive, 1110 .seq_show = blkg_print_stat_ios_recursive,
1090 }, 1111 },
1112#ifdef CONFIG_DEBUG_BLK_CGROUP
1113 {
1114 .name = "bfq.time_recursive",
1115 .private = offsetof(struct bfq_group, stats.time),
1116 .seq_show = bfqg_print_stat_recursive,
1117 },
1118 {
1119 .name = "bfq.sectors_recursive",
1120 .seq_show = bfqg_print_stat_sectors_recursive,
1121 },
1091 { 1122 {
1092 .name = "bfq.io_service_time_recursive", 1123 .name = "bfq.io_service_time_recursive",
1093 .private = offsetof(struct bfq_group, stats.service_time), 1124 .private = offsetof(struct bfq_group, stats.service_time),
@@ -1132,6 +1163,7 @@ struct cftype bfq_blkcg_legacy_files[] = {
1132 .private = offsetof(struct bfq_group, stats.dequeue), 1163 .private = offsetof(struct bfq_group, stats.dequeue),
1133 .seq_show = bfqg_print_stat, 1164 .seq_show = bfqg_print_stat,
1134 }, 1165 },
1166#endif /* CONFIG_DEBUG_BLK_CGROUP */
1135 { } /* terminate */ 1167 { } /* terminate */
1136}; 1168};
1137 1169
@@ -1147,18 +1179,6 @@ struct cftype bfq_blkg_files[] = {
1147 1179
1148#else /* CONFIG_BFQ_GROUP_IOSCHED */ 1180#else /* CONFIG_BFQ_GROUP_IOSCHED */
1149 1181
1150void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
1151 unsigned int op) { }
1152void bfqg_stats_update_io_remove(struct bfq_group *bfqg, unsigned int op) { }
1153void bfqg_stats_update_io_merged(struct bfq_group *bfqg, unsigned int op) { }
1154void bfqg_stats_update_completion(struct bfq_group *bfqg, uint64_t start_time,
1155 uint64_t io_start_time, unsigned int op) { }
1156void bfqg_stats_update_dequeue(struct bfq_group *bfqg) { }
1157void bfqg_stats_set_start_empty_time(struct bfq_group *bfqg) { }
1158void bfqg_stats_update_idle_time(struct bfq_group *bfqg) { }
1159void bfqg_stats_set_start_idle_time(struct bfq_group *bfqg) { }
1160void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg) { }
1161
1162void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, 1182void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
1163 struct bfq_group *bfqg) {} 1183 struct bfq_group *bfqg) {}
1164 1184