@@ -339,7 +339,7 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
EXPORT_SYMBOL(blk_rq_init);
static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
- struct blk_mq_tags *tags, unsigned int tag, u64 alloc_time_ns)
+ struct blk_mq_tags *tags, unsigned int tag, u64 now)
{
struct blk_mq_ctx *ctx = data->ctx;
struct blk_mq_hw_ctx *hctx = data->hctx;
@@ -366,15 +366,11 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
}
rq->timeout = 0;
- if (blk_mq_need_time_stamp(rq))
- rq->start_time_ns = ktime_get_ns();
- else
- rq->start_time_ns = 0;
+ rq->start_time_ns = now;
rq->part = NULL;
#ifdef CONFIG_BLK_RQ_ALLOC_TIME
- rq->alloc_time_ns = alloc_time_ns;
+ rq->alloc_time_ns = now;
#endif
- rq->io_start_time_ns = 0;
rq->stats_sectors = 0;
rq->nr_phys_segments = 0;
#if defined(CONFIG_BLK_DEV_INTEGRITY)
@@ -407,7 +403,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
static inline struct request *
__blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data,
- u64 alloc_time_ns)
+ u64 now)
{
unsigned int tag, tag_offset;
struct blk_mq_tags *tags;
@@ -426,7 +422,7 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data,
tag = tag_offset + i;
prefetch(tags->static_rqs[tag]);
tag_mask &= ~(1UL << i);
- rq = blk_mq_rq_ctx_init(data, tags, tag, alloc_time_ns);
+ rq = blk_mq_rq_ctx_init(data, tags, tag, now);
rq_list_add(data->cached_rq, rq);
nr++;
}
@@ -440,13 +436,13 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data,
static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
{
struct request_queue *q = data->q;
- u64 alloc_time_ns = 0;
struct request *rq;
unsigned int tag;
+ u64 now = 0;
/* alloc_time includes depth and tag waits */
- if (blk_queue_rq_alloc_time(q))
- alloc_time_ns = ktime_get_ns();
+ if (blk_queue_need_ts(q))
+ now = ktime_get_ns();
if (data->cmd_flags & REQ_NOWAIT)
data->flags |= BLK_MQ_REQ_NOWAIT;
@@ -481,7 +477,7 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
* Try batched alloc if we want more than 1 tag.
*/
if (data->nr_tags > 1) {
- rq = __blk_mq_alloc_requests_batch(data, alloc_time_ns);
+ rq = __blk_mq_alloc_requests_batch(data, now);
if (rq)
return rq;
data->nr_tags = 1;
@@ -507,7 +503,7 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
}
return blk_mq_rq_ctx_init(data, blk_mq_tags_from_data(data), tag,
- alloc_time_ns);
+ now);
}
static struct request *blk_mq_rq_cache_fill(struct request_queue *q,
@@ -610,14 +606,14 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
.cmd_flags = opf,
.nr_tags = 1,
};
- u64 alloc_time_ns = 0;
unsigned int cpu;
unsigned int tag;
+ u64 now = 0;
int ret;
/* alloc_time includes depth and tag waits */
- if (blk_queue_rq_alloc_time(q))
- alloc_time_ns = ktime_get_ns();
+ if (blk_queue_need_ts(q))
+ now = ktime_get_ns();
/*
* If the tag allocator sleeps we could get an allocation for a
@@ -661,7 +657,7 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
if (tag == BLK_MQ_NO_TAG)
goto out_queue_exit;
return blk_mq_rq_ctx_init(&data, blk_mq_tags_from_data(&data), tag,
- alloc_time_ns);
+ now);
out_queue_exit:
blk_queue_exit(q);
@@ -1214,8 +1210,13 @@ void blk_mq_start_request(struct request *rq)
trace_block_rq_issue(rq);
- if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {
- rq->io_start_time_ns = ktime_get_ns();
+ if (blk_queue_stat(q) ) {
+ /*
+ * io_start_time_ns may not have been set earlier if the stat
+ * attribute was being changed.
+ */
+ if (!rq->io_start_time_ns)
+ rq->io_start_time_ns = ktime_get_ns();
rq->stats_sectors = blk_rq_sectors(rq);
rq->rq_flags |= RQF_STATS;
rq_qos_issue(q, rq);
@@ -1944,10 +1945,14 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
blk_status_t ret = BLK_STS_OK;
LIST_HEAD(zone_list);
bool needs_resource = false;
+ u64 now = 0;
if (list_empty(list))
return false;
+ if (blk_queue_stat(q))
+ now = ktime_get_ns();
+
/*
* Now process all the entries, sending them to the driver.
*/
@@ -1983,6 +1988,8 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
*/
if (nr_budgets)
nr_budgets--;
+
+ rq->io_start_time_ns = now;
ret = q->mq_ops->queue_rq(hctx, &bd);
switch (ret) {
case BLK_STS_OK:
@@ -2507,7 +2514,7 @@ static void blk_mq_bio_to_request(struct request *rq, struct bio *bio,
}
static blk_status_t __blk_mq_issue_directly(struct blk_mq_hw_ctx *hctx,
- struct request *rq, bool last)
+ struct request *rq, bool last, u64 now)
{
struct request_queue *q = rq->q;
struct blk_mq_queue_data bd = {
@@ -2521,6 +2528,7 @@ static blk_status_t __blk_mq_issue_directly(struct blk_mq_hw_ctx *hctx,
* Any other error (busy), just add it to our list as we
* previously would have done.
*/
+ rq->io_start_time_ns = now;
ret = q->mq_ops->queue_rq(hctx, &bd);
switch (ret) {
case BLK_STS_OK:
@@ -2541,7 +2549,7 @@ static blk_status_t __blk_mq_issue_directly(struct blk_mq_hw_ctx *hctx,
static blk_status_t __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
struct request *rq,
- bool bypass_insert, bool last)
+ bool bypass_insert, bool last, u64 now)
{
struct request_queue *q = rq->q;
bool run_queue = true;
@@ -2574,7 +2582,7 @@ static blk_status_t __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
goto insert;
}
- return __blk_mq_issue_directly(hctx, rq, last);
+ return __blk_mq_issue_directly(hctx, rq, last, now);
insert:
if (bypass_insert)
return BLK_STS_RESOURCE;
@@ -2597,8 +2605,13 @@ static blk_status_t __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
struct request *rq)
{
- blk_status_t ret =
- __blk_mq_try_issue_directly(hctx, rq, false, true);
+ blk_status_t ret;
+ u64 now = 0;
+
+ if (blk_queue_stat(rq->q))
+ now = ktime_get_ns();
+
+ ret = __blk_mq_try_issue_directly(hctx, rq, false, true, now);
if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE)
blk_mq_request_bypass_insert(rq, false, true);
@@ -2606,14 +2619,15 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
blk_mq_end_request(rq, ret);
}
-static blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last)
+static blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last, u64 now)
{
- return __blk_mq_try_issue_directly(rq->mq_hctx, rq, true, last);
+ return __blk_mq_try_issue_directly(rq->mq_hctx, rq, true, last, now);
}
static void blk_mq_plug_issue_direct(struct blk_plug *plug, bool from_schedule)
{
struct blk_mq_hw_ctx *hctx = NULL;
+ u64 now = ktime_get_ns();
struct request *rq;
int queued = 0;
int errors = 0;
@@ -2628,7 +2642,7 @@ static void blk_mq_plug_issue_direct(struct blk_plug *plug, bool from_schedule)
hctx = rq->mq_hctx;
}
- ret = blk_mq_request_issue_directly(rq, last);
+ ret = blk_mq_request_issue_directly(rq, last, now);
switch (ret) {
case BLK_STS_OK:
queued++;
@@ -2656,9 +2670,14 @@ static void blk_mq_plug_issue_direct(struct blk_plug *plug, bool from_schedule)
static void __blk_mq_flush_plug_list(struct request_queue *q,
struct blk_plug *plug)
{
+ u64 now = 0;
+
if (blk_queue_quiesced(q))
return;
- q->mq_ops->queue_rqs(&plug->mq_list);
+ if (blk_queue_stat(q))
+ now = ktime_get_ns();
+
+ q->mq_ops->queue_rqs(&plug->mq_list, now);
}
static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched)
@@ -2736,6 +2755,10 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
{
int queued = 0;
int errors = 0;
+ u64 now = 0;
+
+ if (blk_queue_stat(hctx->queue))
+ now = ktime_get_ns();
while (!list_empty(list)) {
blk_status_t ret;
@@ -2743,7 +2766,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
queuelist);
list_del_init(&rq->queuelist);
- ret = blk_mq_request_issue_directly(rq, list_empty(list));
+ ret = blk_mq_request_issue_directly(rq, list_empty(list), now);
if (ret != BLK_STS_OK) {
errors++;
if (ret == BLK_STS_RESOURCE ||
@@ -2938,6 +2961,7 @@ blk_status_t blk_insert_cloned_request(struct request *rq)
struct request_queue *q = rq->q;
unsigned int max_sectors = blk_queue_get_max_sectors(q, req_op(rq));
blk_status_t ret;
+ u64 now = 0;
if (blk_rq_sectors(rq) > max_sectors) {
/*
@@ -2975,6 +2999,8 @@ blk_status_t blk_insert_cloned_request(struct request *rq)
if (blk_crypto_insert_cloned_request(rq))
return BLK_STS_IOERR;
+ if (blk_do_io_stat(rq))
+ now = ktime_get_ns();
blk_account_io_start(rq);
/*
@@ -2983,7 +3009,7 @@ blk_status_t blk_insert_cloned_request(struct request *rq)
* insert.
*/
blk_mq_run_dispatch_ops(q,
- ret = blk_mq_request_issue_directly(rq, true));
+ ret = blk_mq_request_issue_directly(rq, true, now));
if (ret)
blk_account_io_done(rq, ktime_get_ns());
return ret;
@@ -417,7 +417,7 @@ static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
return kick;
}
-static void virtio_queue_rqs(struct request **rqlist)
+static void virtio_queue_rqs(struct request **rqlist, u64 now)
{
struct request *req, *next, *prev = NULL;
struct request *requeue_list = NULL;
@@ -426,6 +426,7 @@ static void virtio_queue_rqs(struct request **rqlist)
struct virtio_blk_vq *vq = get_virtio_blk_vq(req->mq_hctx);
bool kick;
+ req->io_start_time_ns = now;
if (!virtblk_prep_rq_batch(req)) {
rq_list_move(rqlist, &requeue_list, req, prev);
req = prev;
@@ -981,7 +981,7 @@ static bool nvme_prep_rq_batch(struct nvme_queue *nvmeq, struct request *req)
return nvme_prep_rq(nvmeq->dev, req) == BLK_STS_OK;
}
-static void nvme_queue_rqs(struct request **rqlist)
+static void nvme_queue_rqs(struct request **rqlist, u64 now)
{
struct request *req, *next, *prev = NULL;
struct request *requeue_list = NULL;
@@ -989,6 +989,7 @@ static void nvme_queue_rqs(struct request **rqlist)
rq_list_for_each_safe(rqlist, req, next) {
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
+ req->io_start_time_ns = now;
if (!nvme_prep_rq_batch(nvmeq, req)) {
/* detach 'req' and add to remainder list */
rq_list_move(rqlist, &requeue_list, req, prev);
@@ -562,7 +562,7 @@ struct blk_mq_ops {
* empty the @rqlist completely, then the rest will be queued
* individually by the block layer upon return.
*/
- void (*queue_rqs)(struct request **rqlist);
+ void (*queue_rqs)(struct request **rqlist, u64 now);
/**
* @get_budget: Reserve budget before queue request, once .queue_rq is
@@ -599,6 +599,7 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
#define blk_queue_stable_writes(q) \
test_bit(QUEUE_FLAG_STABLE_WRITES, &(q)->queue_flags)
#define blk_queue_io_stat(q) test_bit(QUEUE_FLAG_IO_STAT, &(q)->queue_flags)
+#define blk_queue_stat(q) test_bit(QUEUE_FLAG_STATS, &(q)->queue_flags)
#define blk_queue_add_random(q) test_bit(QUEUE_FLAG_ADD_RANDOM, &(q)->queue_flags)
#define blk_queue_zone_resetall(q) \
test_bit(QUEUE_FLAG_ZONE_RESETALL, &(q)->queue_flags)
@@ -612,6 +613,12 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
#define blk_queue_rq_alloc_time(q) false
#endif
+#define blk_queue_need_ts(q) \
+ (blk_queue_rq_alloc_time(q) || \
+ blk_queue_stat(q) || \
+ blk_queue_io_stat(q) || \
+ q->elevator)
+
#define blk_noretry_request(rq) \
((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \
REQ_FAILFAST_DRIVER))