block: add scalable completion tracking of requests

For legacy block, we simply track them in the request queue. For
blk-mq, we track them on a per-sw queue basis, which we can then
sum up through the hardware queues and finally to a per device
state.

The stats are tracked in, roughly, 0.1s interval windows.

Add sysfs files to display the stats.

The feature is off by default, to avoid any extra overhead. In-kernel
users of it can turn it on by setting QUEUE_FLAG_STATS in the queue
flags. We currently don't turn it on if someone just reads any of
the stats files, that is something we could add as well.

Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
Jens Axboe
2016-11-07 21:32:37 -07:00
parent ebc4ff661f
commit cf43e6be86
10 changed files with 427 additions and 3 deletions

View File

@@ -2464,6 +2464,11 @@ void blk_start_request(struct request *req)
{
blk_dequeue_request(req);
if (test_bit(QUEUE_FLAG_STATS, &req->q->queue_flags)) {
blk_stat_set_issue_time(&req->issue_stat);
req->rq_flags |= RQF_STATS;
}
/*
* We are now handing the request to the hardware, initialize
* resid_len to full count and add the timeout handler.
@@ -2683,8 +2688,13 @@ EXPORT_SYMBOL_GPL(blk_unprep_request);
*/
void blk_finish_request(struct request *req, int error)
{
struct request_queue *q = req->q;
if (req->rq_flags & RQF_STATS)
blk_stat_add(&q->rq_stats[rq_data_dir(req)], req);
if (req->rq_flags & RQF_QUEUED)
blk_queue_end_tag(req->q, req);
blk_queue_end_tag(q, req);
BUG_ON(blk_queued_rq(req));
@@ -2704,7 +2714,7 @@ void blk_finish_request(struct request *req, int error)
if (blk_bidi_rq(req))
__blk_put_request(req->next_rq->q, req->next_rq);
__blk_put_request(req->q, req);
__blk_put_request(q, req);
}
}
EXPORT_SYMBOL(blk_finish_request);