summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2018-09-27 18:55:55 -0400
committerJens Axboe <axboe@kernel.dk>2018-09-27 19:34:59 -0400
commit6c3b7af1c975b87b86dcb2af233d1ae21eb05107 (patch)
tree9854b83cbab19565d416620bd303c38847f2e856 /block
parent6e25cb01ea206362616a2be469d4f3635f58ca63 (diff)
kyber: add tracepoints
When debugging Kyber, it's really useful to know what latencies we've been having, how the domain depths have been adjusted, and if we've actually been throttling. Add three tracepoints, kyber_latency, kyber_adjust, and kyber_throttled, to record that. Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/kyber-iosched.c52
1 files changed, 34 insertions, 18 deletions
diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c
index adc8e6393829..2b62e362fb36 100644
--- a/block/kyber-iosched.c
+++ b/block/kyber-iosched.c
@@ -30,6 +30,9 @@
30#include "blk-mq-sched.h" 30#include "blk-mq-sched.h"
31#include "blk-mq-tag.h" 31#include "blk-mq-tag.h"
32 32
33#define CREATE_TRACE_POINTS
34#include <trace/events/kyber.h>
35
33/* 36/*
34 * Scheduling domains: the device is divided into multiple domains based on the 37 * Scheduling domains: the device is divided into multiple domains based on the
35 * request type. 38 * request type.
@@ -42,6 +45,13 @@ enum {
42 KYBER_NUM_DOMAINS, 45 KYBER_NUM_DOMAINS,
43}; 46};
44 47
48static const char *kyber_domain_names[] = {
49 [KYBER_READ] = "READ",
50 [KYBER_WRITE] = "WRITE",
51 [KYBER_DISCARD] = "DISCARD",
52 [KYBER_OTHER] = "OTHER",
53};
54
45enum { 55enum {
46 /* 56 /*
47 * In order to prevent starvation of synchronous requests by a flood of 57 * In order to prevent starvation of synchronous requests by a flood of
@@ -122,6 +132,11 @@ enum {
122 KYBER_IO_LATENCY, 132 KYBER_IO_LATENCY,
123}; 133};
124 134
135static const char *kyber_latency_type_names[] = {
136 [KYBER_TOTAL_LATENCY] = "total",
137 [KYBER_IO_LATENCY] = "I/O",
138};
139
125/* 140/*
126 * Per-cpu latency histograms: total latency and I/O latency for each scheduling 141 * Per-cpu latency histograms: total latency and I/O latency for each scheduling
127 * domain except for KYBER_OTHER. 142 * domain except for KYBER_OTHER.
@@ -144,6 +159,8 @@ struct kyber_ctx_queue {
144} ____cacheline_aligned_in_smp; 159} ____cacheline_aligned_in_smp;
145 160
146struct kyber_queue_data { 161struct kyber_queue_data {
162 struct request_queue *q;
163
147 /* 164 /*
148 * Each scheduling domain has a limited number of in-flight requests 165 * Each scheduling domain has a limited number of in-flight requests
149 * device-wide, limited by these tokens. 166 * device-wide, limited by these tokens.
@@ -249,6 +266,10 @@ static int calculate_percentile(struct kyber_queue_data *kqd,
249 } 266 }
250 memset(buckets, 0, sizeof(kqd->latency_buckets[sched_domain][type])); 267 memset(buckets, 0, sizeof(kqd->latency_buckets[sched_domain][type]));
251 268
269 trace_kyber_latency(kqd->q, kyber_domain_names[sched_domain],
270 kyber_latency_type_names[type], percentile,
271 bucket + 1, 1 << KYBER_LATENCY_SHIFT, samples);
272
252 return bucket; 273 return bucket;
253} 274}
254 275
@@ -256,8 +277,11 @@ static void kyber_resize_domain(struct kyber_queue_data *kqd,
256 unsigned int sched_domain, unsigned int depth) 277 unsigned int sched_domain, unsigned int depth)
257{ 278{
258 depth = clamp(depth, 1U, kyber_depth[sched_domain]); 279 depth = clamp(depth, 1U, kyber_depth[sched_domain]);
259 if (depth != kqd->domain_tokens[sched_domain].sb.depth) 280 if (depth != kqd->domain_tokens[sched_domain].sb.depth) {
260 sbitmap_queue_resize(&kqd->domain_tokens[sched_domain], depth); 281 sbitmap_queue_resize(&kqd->domain_tokens[sched_domain], depth);
282 trace_kyber_adjust(kqd->q, kyber_domain_names[sched_domain],
283 depth);
284 }
261} 285}
262 286
263static void kyber_timer_fn(struct timer_list *t) 287static void kyber_timer_fn(struct timer_list *t)
@@ -360,6 +384,8 @@ static struct kyber_queue_data *kyber_queue_data_alloc(struct request_queue *q)
360 if (!kqd) 384 if (!kqd)
361 goto err; 385 goto err;
362 386
387 kqd->q = q;
388
363 kqd->cpu_latency = alloc_percpu_gfp(struct kyber_cpu_latency, 389 kqd->cpu_latency = alloc_percpu_gfp(struct kyber_cpu_latency,
364 GFP_KERNEL | __GFP_ZERO); 390 GFP_KERNEL | __GFP_ZERO);
365 if (!kqd->cpu_latency) 391 if (!kqd->cpu_latency)
@@ -756,6 +782,9 @@ kyber_dispatch_cur_domain(struct kyber_queue_data *kqd,
756 rq_set_domain_token(rq, nr); 782 rq_set_domain_token(rq, nr);
757 list_del_init(&rq->queuelist); 783 list_del_init(&rq->queuelist);
758 return rq; 784 return rq;
785 } else {
786 trace_kyber_throttled(kqd->q,
787 kyber_domain_names[khd->cur_domain]);
759 } 788 }
760 } else if (sbitmap_any_bit_set(&khd->kcq_map[khd->cur_domain])) { 789 } else if (sbitmap_any_bit_set(&khd->kcq_map[khd->cur_domain])) {
761 nr = kyber_get_domain_token(kqd, khd, hctx); 790 nr = kyber_get_domain_token(kqd, khd, hctx);
@@ -766,6 +795,9 @@ kyber_dispatch_cur_domain(struct kyber_queue_data *kqd,
766 rq_set_domain_token(rq, nr); 795 rq_set_domain_token(rq, nr);
767 list_del_init(&rq->queuelist); 796 list_del_init(&rq->queuelist);
768 return rq; 797 return rq;
798 } else {
799 trace_kyber_throttled(kqd->q,
800 kyber_domain_names[khd->cur_domain]);
769 } 801 }
770 } 802 }
771 803
@@ -944,23 +976,7 @@ static int kyber_cur_domain_show(void *data, struct seq_file *m)
944 struct blk_mq_hw_ctx *hctx = data; 976 struct blk_mq_hw_ctx *hctx = data;
945 struct kyber_hctx_data *khd = hctx->sched_data; 977 struct kyber_hctx_data *khd = hctx->sched_data;
946 978
947 switch (khd->cur_domain) { 979 seq_printf(m, "%s\n", kyber_domain_names[khd->cur_domain]);
948 case KYBER_READ:
949 seq_puts(m, "READ\n");
950 break;
951 case KYBER_WRITE:
952 seq_puts(m, "WRITE\n");
953 break;
954 case KYBER_DISCARD:
955 seq_puts(m, "DISCARD\n");
956 break;
957 case KYBER_OTHER:
958 seq_puts(m, "OTHER\n");
959 break;
960 default:
961 seq_printf(m, "%u\n", khd->cur_domain);
962 break;
963 }
964 return 0; 980 return 0;
965} 981}
966 982