diff options
author | Omar Sandoval <osandov@fb.com> | 2018-05-09 05:08:53 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-05-09 10:33:09 -0400 |
commit | 522a777566f5669606a1227bf13f3fb40963780b (patch) | |
tree | 7d37c9d591e5a9abb4fd1209f1c503ae1a0e8475 /block | |
parent | 4bc6339a583cec650b05d6fdcc83f03f941c1a3b (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.c | 4 | ||||
-rw-r--r-- | block/blk-core.c | 17 | ||||
-rw-r--r-- | block/blk-merge.c | 11 | ||||
-rw-r--r-- | block/blk-mq.c | 10 | ||||
-rw-r--r-- | block/blk-stat.c | 5 | ||||
-rw-r--r-- | block/blk-stat.h | 2 | ||||
-rw-r--r-- | block/blk.h | 2 | ||||
-rw-r--r-- | block/cfq-iosched.c | 15 |
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 | ||
2729 | void blk_account_io_done(struct request *req) | 2728 | void 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); | |||
3192 | void blk_finish_request(struct request *req, blk_status_t error) | 3190 | void 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 | ||
507 | inline void __blk_mq_end_request(struct request *rq, blk_status_t error) | 505 | inline 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 | ||
50 | void blk_stat_add(struct request *rq) | 50 | void 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 { | |||
65 | struct blk_queue_stats *blk_alloc_queue_stats(void); | 65 | struct blk_queue_stats *blk_alloc_queue_stats(void); |
66 | void blk_free_queue_stats(struct blk_queue_stats *); | 66 | void blk_free_queue_stats(struct blk_queue_stats *); |
67 | 67 | ||
68 | void blk_stat_add(struct request *); | 68 | void 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 */ |
71 | void blk_stat_enable_accounting(struct request_queue *q); | 71 | void 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 | ||
187 | void blk_account_io_start(struct request *req, bool new_io); | 187 | void blk_account_io_start(struct request *req, bool new_io); |
188 | void blk_account_io_completion(struct request *req, unsigned int bytes); | 188 | void blk_account_io_completion(struct request *req, unsigned int bytes); |
189 | void blk_account_io_done(struct request *req); | 189 | void 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 | ||