summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2018-05-09 05:08:53 -0400
committerJens Axboe <axboe@kernel.dk>2018-05-09 10:33:09 -0400
commit522a777566f5669606a1227bf13f3fb40963780b (patch)
tree7d37c9d591e5a9abb4fd1209f1c503ae1a0e8475 /block
parent4bc6339a583cec650b05d6fdcc83f03f941c1a3b (diff)
block: consolidate struct request timestamp fields
Currently, struct request has four timestamp fields: - A start time, set at get_request time, in jiffies, used for iostats - An I/O start time, set at start_request time, in ktime nanoseconds, used for blk-stats (i.e., wbt, kyber, hybrid polling) - Another start time and another I/O start time, used for cfq and bfq These can all be consolidated into one start time and one I/O start time, both in ktime nanoseconds, shaving off up to 16 bytes from struct request depending on the kernel config. Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/bfq-iosched.c4
-rw-r--r--block/blk-core.c17
-rw-r--r--block/blk-merge.c11
-rw-r--r--block/blk-mq.c10
-rw-r--r--block/blk-stat.c5
-rw-r--r--block/blk-stat.h2
-rw-r--r--block/blk.h2
-rw-r--r--block/cfq-iosched.c15
8 files changed, 27 insertions, 39 deletions
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 771ae9730ac6..ebc264c87a09 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -4778,8 +4778,8 @@ static void bfq_finish_requeue_request(struct request *rq)
4778 4778
4779 if (rq->rq_flags & RQF_STARTED) 4779 if (rq->rq_flags & RQF_STARTED)
4780 bfqg_stats_update_completion(bfqq_group(bfqq), 4780 bfqg_stats_update_completion(bfqq_group(bfqq),
4781 rq_start_time_ns(rq), 4781 rq->start_time_ns,
4782 rq_io_start_time_ns(rq), 4782 rq->io_start_time_ns,
4783 rq->cmd_flags); 4783 rq->cmd_flags);
4784 4784
4785 if (likely(rq->rq_flags & RQF_STARTED)) { 4785 if (likely(rq->rq_flags & RQF_STARTED)) {
diff --git a/block/blk-core.c b/block/blk-core.c
index 33d5c7d85da1..1418a1ccd80d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -196,8 +196,7 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
196 RB_CLEAR_NODE(&rq->rb_node); 196 RB_CLEAR_NODE(&rq->rb_node);
197 rq->tag = -1; 197 rq->tag = -1;
198 rq->internal_tag = -1; 198 rq->internal_tag = -1;
199 rq->start_time = jiffies; 199 rq->start_time_ns = ktime_get_ns();
200 set_start_time_ns(rq);
201 rq->part = NULL; 200 rq->part = NULL;
202 seqcount_init(&rq->gstate_seq); 201 seqcount_init(&rq->gstate_seq);
203 u64_stats_init(&rq->aborted_gstate_sync); 202 u64_stats_init(&rq->aborted_gstate_sync);
@@ -2726,7 +2725,7 @@ void blk_account_io_completion(struct request *req, unsigned int bytes)
2726 } 2725 }
2727} 2726}
2728 2727
2729void blk_account_io_done(struct request *req) 2728void blk_account_io_done(struct request *req, u64 now)
2730{ 2729{
2731 /* 2730 /*
2732 * Account IO completion. flush_rq isn't accounted as a 2731 * Account IO completion. flush_rq isn't accounted as a
@@ -2734,11 +2733,12 @@ void blk_account_io_done(struct request *req)
2734 * containing request is enough. 2733 * containing request is enough.
2735 */ 2734 */
2736 if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) { 2735 if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) {
2737 unsigned long duration = jiffies - req->start_time; 2736 unsigned long duration;
2738 const int rw = rq_data_dir(req); 2737 const int rw = rq_data_dir(req);
2739 struct hd_struct *part; 2738 struct hd_struct *part;
2740 int cpu; 2739 int cpu;
2741 2740
2741 duration = nsecs_to_jiffies(now - req->start_time_ns);
2742 cpu = part_stat_lock(); 2742 cpu = part_stat_lock();
2743 part = req->part; 2743 part = req->part;
2744 2744
@@ -2969,10 +2969,8 @@ static void blk_dequeue_request(struct request *rq)
2969 * and to it is freed is accounted as io that is in progress at 2969 * and to it is freed is accounted as io that is in progress at
2970 * the driver side. 2970 * the driver side.
2971 */ 2971 */
2972 if (blk_account_rq(rq)) { 2972 if (blk_account_rq(rq))
2973 q->in_flight[rq_is_sync(rq)]++; 2973 q->in_flight[rq_is_sync(rq)]++;
2974 set_io_start_time_ns(rq);
2975 }
2976} 2974}
2977 2975
2978/** 2976/**
@@ -3192,12 +3190,13 @@ EXPORT_SYMBOL_GPL(blk_unprep_request);
3192void blk_finish_request(struct request *req, blk_status_t error) 3190void blk_finish_request(struct request *req, blk_status_t error)
3193{ 3191{
3194 struct request_queue *q = req->q; 3192 struct request_queue *q = req->q;
3193 u64 now = ktime_get_ns();
3195 3194
3196 lockdep_assert_held(req->q->queue_lock); 3195 lockdep_assert_held(req->q->queue_lock);
3197 WARN_ON_ONCE(q->mq_ops); 3196 WARN_ON_ONCE(q->mq_ops);
3198 3197
3199 if (req->rq_flags & RQF_STATS) 3198 if (req->rq_flags & RQF_STATS)
3200 blk_stat_add(req); 3199 blk_stat_add(req, now);
3201 3200
3202 if (req->rq_flags & RQF_QUEUED) 3201 if (req->rq_flags & RQF_QUEUED)
3203 blk_queue_end_tag(q, req); 3202 blk_queue_end_tag(q, req);
@@ -3212,7 +3211,7 @@ void blk_finish_request(struct request *req, blk_status_t error)
3212 if (req->rq_flags & RQF_DONTPREP) 3211 if (req->rq_flags & RQF_DONTPREP)
3213 blk_unprep_request(req); 3212 blk_unprep_request(req);
3214 3213
3215 blk_account_io_done(req); 3214 blk_account_io_done(req, now);
3216 3215
3217 if (req->end_io) { 3216 if (req->end_io) {
3218 wbt_done(req->q->rq_wb, req); 3217 wbt_done(req->q->rq_wb, req);
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 782940c65d8a..5573d0fbec53 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -724,13 +724,12 @@ static struct request *attempt_merge(struct request_queue *q,
724 } 724 }
725 725
726 /* 726 /*
727 * At this point we have either done a back merge 727 * At this point we have either done a back merge or front merge. We
728 * or front merge. We need the smaller start_time of 728 * need the smaller start_time_ns of the merged requests to be the
729 * the merged requests to be the current request 729 * current request for accounting purposes.
730 * for accounting purposes.
731 */ 730 */
732 if (time_after(req->start_time, next->start_time)) 731 if (next->start_time_ns < req->start_time_ns)
733 req->start_time = next->start_time; 732 req->start_time_ns = next->start_time_ns;
734 733
735 req->biotail->bi_next = next->bio; 734 req->biotail->bi_next = next->bio;
736 req->biotail = next->biotail; 735 req->biotail = next->biotail;
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 39b4e9834d82..4e9d83594cca 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -309,7 +309,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
309 RB_CLEAR_NODE(&rq->rb_node); 309 RB_CLEAR_NODE(&rq->rb_node);
310 rq->rq_disk = NULL; 310 rq->rq_disk = NULL;
311 rq->part = NULL; 311 rq->part = NULL;
312 rq->start_time = jiffies; 312 rq->start_time_ns = ktime_get_ns();
313 rq->io_start_time_ns = 0; 313 rq->io_start_time_ns = 0;
314 rq->nr_phys_segments = 0; 314 rq->nr_phys_segments = 0;
315#if defined(CONFIG_BLK_DEV_INTEGRITY) 315#if defined(CONFIG_BLK_DEV_INTEGRITY)
@@ -329,8 +329,6 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
329 329
330#ifdef CONFIG_BLK_CGROUP 330#ifdef CONFIG_BLK_CGROUP
331 rq->rl = NULL; 331 rq->rl = NULL;
332 set_start_time_ns(rq);
333 rq->cgroup_io_start_time_ns = 0;
334#endif 332#endif
335 333
336 data->ctx->rq_dispatched[op_is_sync(op)]++; 334 data->ctx->rq_dispatched[op_is_sync(op)]++;
@@ -506,12 +504,14 @@ EXPORT_SYMBOL_GPL(blk_mq_free_request);
506 504
507inline void __blk_mq_end_request(struct request *rq, blk_status_t error) 505inline void __blk_mq_end_request(struct request *rq, blk_status_t error)
508{ 506{
507 u64 now = ktime_get_ns();
508
509 if (rq->rq_flags & RQF_STATS) { 509 if (rq->rq_flags & RQF_STATS) {
510 blk_mq_poll_stats_start(rq->q); 510 blk_mq_poll_stats_start(rq->q);
511 blk_stat_add(rq); 511 blk_stat_add(rq, now);
512 } 512 }
513 513
514 blk_account_io_done(rq); 514 blk_account_io_done(rq, now);
515 515
516 if (rq->end_io) { 516 if (rq->end_io) {
517 wbt_done(rq->q->rq_wb, rq); 517 wbt_done(rq->q->rq_wb, rq);
diff --git a/block/blk-stat.c b/block/blk-stat.c
index 725a881723b0..175c143ac5b9 100644
--- a/block/blk-stat.c
+++ b/block/blk-stat.c
@@ -47,15 +47,14 @@ static void __blk_stat_add(struct blk_rq_stat *stat, u64 value)
47 stat->nr_samples++; 47 stat->nr_samples++;
48} 48}
49 49
50void blk_stat_add(struct request *rq) 50void blk_stat_add(struct request *rq, u64 now)
51{ 51{
52 struct request_queue *q = rq->q; 52 struct request_queue *q = rq->q;
53 struct blk_stat_callback *cb; 53 struct blk_stat_callback *cb;
54 struct blk_rq_stat *stat; 54 struct blk_rq_stat *stat;
55 int bucket; 55 int bucket;
56 u64 now, value; 56 u64 value;
57 57
58 now = ktime_get_ns();
59 value = (now >= rq->io_start_time_ns) ? now - rq->io_start_time_ns : 0; 58 value = (now >= rq->io_start_time_ns) ? now - rq->io_start_time_ns : 0;
60 59
61 blk_throtl_stat_add(rq, value); 60 blk_throtl_stat_add(rq, value);
diff --git a/block/blk-stat.h b/block/blk-stat.h
index 17c812db0aca..78399cdde9c9 100644
--- a/block/blk-stat.h
+++ b/block/blk-stat.h
@@ -65,7 +65,7 @@ struct blk_stat_callback {
65struct blk_queue_stats *blk_alloc_queue_stats(void); 65struct blk_queue_stats *blk_alloc_queue_stats(void);
66void blk_free_queue_stats(struct blk_queue_stats *); 66void blk_free_queue_stats(struct blk_queue_stats *);
67 67
68void blk_stat_add(struct request *); 68void blk_stat_add(struct request *rq, u64 now);
69 69
70/* record time/size info in request but not add a callback */ 70/* record time/size info in request but not add a callback */
71void blk_stat_enable_accounting(struct request_queue *q); 71void blk_stat_enable_accounting(struct request_queue *q);
diff --git a/block/blk.h b/block/blk.h
index b034fd2460c4..eaf1a8e87d11 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -186,7 +186,7 @@ unsigned int blk_plug_queued_count(struct request_queue *q);
186 186
187void blk_account_io_start(struct request *req, bool new_io); 187void blk_account_io_start(struct request *req, bool new_io);
188void blk_account_io_completion(struct request *req, unsigned int bytes); 188void blk_account_io_completion(struct request *req, unsigned int bytes);
189void blk_account_io_done(struct request *req); 189void blk_account_io_done(struct request *req, u64 now);
190 190
191/* 191/*
192 * EH timer and IO completion will both attempt to 'grab' the request, make 192 * EH timer and IO completion will both attempt to 'grab' the request, make
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 652ca064de20..6b9f6b1cd33b 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -4228,8 +4228,8 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
4228 cfqd->rq_in_driver--; 4228 cfqd->rq_in_driver--;
4229 cfqq->dispatched--; 4229 cfqq->dispatched--;
4230 (RQ_CFQG(rq))->dispatched--; 4230 (RQ_CFQG(rq))->dispatched--;
4231 cfqg_stats_update_completion(cfqq->cfqg, rq_start_time_ns(rq), 4231 cfqg_stats_update_completion(cfqq->cfqg, rq->start_time_ns,
4232 rq_io_start_time_ns(rq), rq->cmd_flags); 4232 rq->io_start_time_ns, rq->cmd_flags);
4233 4233
4234 cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--; 4234 cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
4235 4235
@@ -4245,16 +4245,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
4245 cfqq_type(cfqq)); 4245 cfqq_type(cfqq));
4246 4246
4247 st->ttime.last_end_request = now; 4247 st->ttime.last_end_request = now;
4248 /* 4248 if (rq->start_time_ns + cfqd->cfq_fifo_expire[1] <= now)
4249 * We have to do this check in jiffies since start_time is in
4250 * jiffies and it is not trivial to convert to ns. If
4251 * cfq_fifo_expire[1] ever comes close to 1 jiffie, this test
4252 * will become problematic but so far we are fine (the default
4253 * is 128 ms).
4254 */
4255 if (!time_after(rq->start_time +
4256 nsecs_to_jiffies(cfqd->cfq_fifo_expire[1]),
4257 jiffies))
4258 cfqd->last_delayed_sync = now; 4249 cfqd->last_delayed_sync = now;
4259 } 4250 }
4260 4251