summaryrefslogtreecommitdiff
path: root/drivers/md/dm-stats.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-stats.c')
-rw-r--r--drivers/md/dm-stats.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c
index 35d368c418d0..0e039a8c0bf2 100644
--- a/drivers/md/dm-stats.c
+++ b/drivers/md/dm-stats.c
@@ -195,6 +195,7 @@ void dm_stats_init(struct dm_stats *stats)
mutex_init(&stats->mutex);
INIT_LIST_HEAD(&stats->list);
+ stats->precise_timestamps = false;
stats->last = alloc_percpu(struct dm_stats_last_position);
for_each_possible_cpu(cpu) {
last = per_cpu_ptr(stats->last, cpu);
@@ -231,6 +232,22 @@ void dm_stats_cleanup(struct dm_stats *stats)
mutex_destroy(&stats->mutex);
}
+static void dm_stats_recalc_precise_timestamps(struct dm_stats *stats)
+{
+ struct list_head *l;
+ struct dm_stat *tmp_s;
+ bool precise_timestamps = false;
+
+ list_for_each(l, &stats->list) {
+ tmp_s = container_of(l, struct dm_stat, list_entry);
+ if (tmp_s->stat_flags & STAT_PRECISE_TIMESTAMPS) {
+ precise_timestamps = true;
+ break;
+ }
+ }
+ stats->precise_timestamps = precise_timestamps;
+}
+
static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
sector_t step, unsigned stat_flags,
unsigned n_histogram_entries,
@@ -376,6 +393,9 @@ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
}
ret_id = s->id;
list_add_tail_rcu(&s->list_entry, l);
+
+ dm_stats_recalc_precise_timestamps(stats);
+
mutex_unlock(&stats->mutex);
resume_callback(md);
@@ -418,6 +438,9 @@ static int dm_stats_delete(struct dm_stats *stats, int id)
}
list_del_rcu(&s->list_entry);
+
+ dm_stats_recalc_precise_timestamps(stats);
+
mutex_unlock(&stats->mutex);
/*
@@ -621,13 +644,14 @@ static void __dm_stat_bio(struct dm_stat *s, int bi_rw,
void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
sector_t bi_sector, unsigned bi_sectors, bool end,
- unsigned long duration_jiffies,
+ unsigned long start_time,
struct dm_stats_aux *stats_aux)
{
struct dm_stat *s;
sector_t end_sector;
struct dm_stats_last_position *last;
bool got_precise_time;
+ unsigned long duration_jiffies = 0;
if (unlikely(!bi_sectors))
return;
@@ -647,16 +671,16 @@ void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
));
WRITE_ONCE(last->last_sector, end_sector);
WRITE_ONCE(last->last_rw, bi_rw);
- }
+ } else
+ duration_jiffies = jiffies - start_time;
rcu_read_lock();
got_precise_time = false;
list_for_each_entry_rcu(s, &stats->list, list_entry) {
if (s->stat_flags & STAT_PRECISE_TIMESTAMPS && !got_precise_time) {
- if (!end)
- stats_aux->duration_ns = ktime_to_ns(ktime_get());
- else
+ /* start (!end) duration_ns is set by DM core's alloc_io() */
+ if (end)
stats_aux->duration_ns = ktime_to_ns(ktime_get()) - stats_aux->duration_ns;
got_precise_time = true;
}