summaryrefslogtreecommitdiff
path: root/block/blk-stat.c
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-10-20 00:10:27 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-10-20 00:10:27 -0300
commitd0b2f91bede3bd5e3d24dd6803e56eee959c1797 (patch)
tree7fee4ab0509879c373c4f2cbd5b8a5be5b4041ee /block/blk-stat.c
parente914f8eb445e8f74b00303c19c2ffceaedd16a05 (diff)
Linux-libre 4.8.2-gnupck-4.8.2-gnu
Diffstat (limited to 'block/blk-stat.c')
-rw-r--r--block/blk-stat.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/block/blk-stat.c b/block/blk-stat.c
index 8e3974d87..bdb16d84b 100644
--- a/block/blk-stat.c
+++ b/block/blk-stat.c
@@ -9,11 +9,29 @@
#include "blk-stat.h"
#include "blk-mq.h"
+static void blk_stat_flush_batch(struct blk_rq_stat *stat)
+{
+ if (!stat->nr_batch)
+ return;
+ if (!stat->nr_samples)
+ stat->mean = div64_s64(stat->batch, stat->nr_batch);
+ else {
+ stat->mean = div64_s64((stat->mean * stat->nr_samples) +
+ stat->batch,
+ stat->nr_samples + stat->nr_batch);
+ }
+
+ stat->nr_samples += stat->nr_batch;
+ stat->nr_batch = stat->batch = 0;
+}
+
void blk_stat_sum(struct blk_rq_stat *dst, struct blk_rq_stat *src)
{
if (!src->nr_samples)
return;
+ blk_stat_flush_batch(src);
+
dst->min = min(dst->min, src->min);
dst->max = max(dst->max, src->max);
@@ -31,6 +49,7 @@ static void blk_mq_stat_get(struct request_queue *q, struct blk_rq_stat *dst)
{
struct blk_mq_hw_ctx *hctx;
struct blk_mq_ctx *ctx;
+ uint64_t latest = 0;
int i, j, nr;
blk_stat_init(&dst[0]);
@@ -58,6 +77,9 @@ static void blk_mq_stat_get(struct request_queue *q, struct blk_rq_stat *dst)
if (!newest)
break;
+ if (newest > latest)
+ latest = newest;
+
queue_for_each_hw_ctx(q, hctx, i) {
hctx_for_each_ctx(hctx, ctx, j) {
if (ctx->stat[0].time == newest) {
@@ -75,6 +97,8 @@ static void blk_mq_stat_get(struct request_queue *q, struct blk_rq_stat *dst)
* Should be very rare.
*/
} while (!nr);
+
+ dst[0].time = dst[1].time = latest;
}
void blk_queue_stat_get(struct request_queue *q, struct blk_rq_stat *dst)
@@ -132,6 +156,7 @@ static void __blk_stat_init(struct blk_rq_stat *stat, s64 time_now)
{
stat->min = -1ULL;
stat->max = stat->nr_samples = stat->mean = 0;
+ stat->batch = stat->nr_batch = 0;
stat->time = time_now & BLK_STAT_MASK;
}
@@ -140,16 +165,26 @@ void blk_stat_init(struct blk_rq_stat *stat)
__blk_stat_init(stat, ktime_to_ns(ktime_get()));
}
+static bool __blk_stat_is_current(struct blk_rq_stat *stat, s64 now)
+{
+ return (now & BLK_STAT_MASK) == (stat->time & BLK_STAT_MASK);
+}
+
+bool blk_stat_is_current(struct blk_rq_stat *stat)
+{
+ return __blk_stat_is_current(stat, ktime_to_ns(ktime_get()));
+}
+
void blk_stat_add(struct blk_rq_stat *stat, struct request *rq)
{
- s64 delta, now, value;
+ s64 now, value;
u64 rq_time = wbt_issue_stat_get_time(&rq->wb_stat);
now = ktime_to_ns(ktime_get());
if (now < rq_time)
return;
- if ((now & BLK_STAT_MASK) != (stat->time & BLK_STAT_MASK))
+ if (!__blk_stat_is_current(stat, now))
__blk_stat_init(stat, now);
value = now - rq_time;
@@ -158,11 +193,12 @@ void blk_stat_add(struct blk_rq_stat *stat, struct request *rq)
if (value < stat->min)
stat->min = value;
- delta = value - stat->mean;
- if (delta)
- stat->mean += div64_s64(delta, stat->nr_samples + 1);
+ if (stat->batch + value < stat->batch ||
+ stat->nr_batch + 1 == BLK_RQ_STAT_BATCH)
+ blk_stat_flush_batch(stat);
- stat->nr_samples++;
+ stat->batch += value;
+ stat->nr_batch++;
}
void blk_stat_clear(struct request_queue *q)