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 commitb879f915bc
("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:b879f915bc
("dm: properly fix redundant bio-based IO accounting") Cc: stable@vger.kernel.org Co-developed-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
8d394bc4ad
commit
0cdb90f0f3
@ -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)
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
io->start_time = jiffies;
|
io->start_time = jiffies;
|
||||||
|
|
||||||
|
dm_stats_record_start(&md->stats, &io->stats_aux);
|
||||||
|
|
||||||
return io;
|
return io;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user