Commit 0cdb90f0 authored by Mike Snitzer's avatar Mike Snitzer

dm stats: fix too short end duration_ns when using precise_timestamps

dm_stats_account_io()'s STAT_PRECISE_TIMESTAMPS support doesn't handle
the fact that with commit b879f915 ("dm: properly fix redundant
bio-based IO accounting") io->start_time _may_ be in the past (meaning
the start_io_acct() was deferred until later).

Add a new dm_stats_recalc_precise_timestamps() helper that will
set/clear a new 'precise_timestamps' flag in the dm_stats struct based
on whether any configured stats enable STAT_PRECISE_TIMESTAMPS.
And update DM core's alloc_io() to use dm_stats_record_start() to set
stats_aux.duration_ns if stats->precise_timestamps is true.

Also, remove unused 'last_sector' and 'last_rw' members from the
dm_stats struct.

Fixes: b879f915 ("dm: properly fix redundant bio-based IO accounting")
Cc: stable@vger.kernel.org
Co-developed-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 8d394bc4
...@@ -195,6 +195,7 @@ void dm_stats_init(struct dm_stats *stats) ...@@ -195,6 +195,7 @@ void dm_stats_init(struct dm_stats *stats)
mutex_init(&stats->mutex); mutex_init(&stats->mutex);
INIT_LIST_HEAD(&stats->list); INIT_LIST_HEAD(&stats->list);
stats->precise_timestamps = false;
stats->last = alloc_percpu(struct dm_stats_last_position); stats->last = alloc_percpu(struct dm_stats_last_position);
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
last = per_cpu_ptr(stats->last, cpu); last = per_cpu_ptr(stats->last, cpu);
...@@ -231,6 +232,22 @@ void dm_stats_cleanup(struct dm_stats *stats) ...@@ -231,6 +232,22 @@ void dm_stats_cleanup(struct dm_stats *stats)
mutex_destroy(&stats->mutex); 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, static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
sector_t step, unsigned stat_flags, sector_t step, unsigned stat_flags,
unsigned n_histogram_entries, unsigned n_histogram_entries,
...@@ -376,6 +393,9 @@ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end, ...@@ -376,6 +393,9 @@ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
} }
ret_id = s->id; ret_id = s->id;
list_add_tail_rcu(&s->list_entry, l); list_add_tail_rcu(&s->list_entry, l);
dm_stats_recalc_precise_timestamps(stats);
mutex_unlock(&stats->mutex); mutex_unlock(&stats->mutex);
resume_callback(md); resume_callback(md);
...@@ -418,6 +438,9 @@ static int dm_stats_delete(struct dm_stats *stats, int id) ...@@ -418,6 +438,9 @@ static int dm_stats_delete(struct dm_stats *stats, int id)
} }
list_del_rcu(&s->list_entry); list_del_rcu(&s->list_entry);
dm_stats_recalc_precise_timestamps(stats);
mutex_unlock(&stats->mutex); mutex_unlock(&stats->mutex);
/* /*
...@@ -656,9 +679,8 @@ void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw, ...@@ -656,9 +679,8 @@ void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
got_precise_time = false; got_precise_time = false;
list_for_each_entry_rcu(s, &stats->list, list_entry) { list_for_each_entry_rcu(s, &stats->list, list_entry) {
if (s->stat_flags & STAT_PRECISE_TIMESTAMPS && !got_precise_time) { if (s->stat_flags & STAT_PRECISE_TIMESTAMPS && !got_precise_time) {
if (!end) /* start (!end) duration_ns is set by DM core's alloc_io() */
stats_aux->duration_ns = ktime_to_ns(ktime_get()); if (end)
else
stats_aux->duration_ns = ktime_to_ns(ktime_get()) - stats_aux->duration_ns; stats_aux->duration_ns = ktime_to_ns(ktime_get()) - stats_aux->duration_ns;
got_precise_time = true; got_precise_time = true;
} }
......
...@@ -13,8 +13,7 @@ struct dm_stats { ...@@ -13,8 +13,7 @@ struct dm_stats {
struct mutex mutex; struct mutex mutex;
struct list_head list; /* list of struct dm_stat */ struct list_head list; /* list of struct dm_stat */
struct dm_stats_last_position __percpu *last; struct dm_stats_last_position __percpu *last;
sector_t last_sector; bool precise_timestamps;
unsigned last_rw;
}; };
struct dm_stats_aux { struct dm_stats_aux {
...@@ -40,4 +39,10 @@ static inline bool dm_stats_used(struct dm_stats *st) ...@@ -40,4 +39,10 @@ static inline bool dm_stats_used(struct dm_stats *st)
return !list_empty(&st->list); return !list_empty(&st->list);
} }
static inline void dm_stats_record_start(struct dm_stats *stats, struct dm_stats_aux *aux)
{
if (unlikely(stats->precise_timestamps))
aux->duration_ns = ktime_to_ns(ktime_get());
}
#endif #endif
...@@ -552,6 +552,8 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) ...@@ -552,6 +552,8 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio)
io->start_time = jiffies; io->start_time = jiffies;
dm_stats_record_start(&md->stats, &io->stats_aux);
return io; return io;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment