[dm-devel] [PATCH 2/4] dm stats: support precise timestamps

Mike Snitzer snitzer at redhat.com
Wed Jun 10 17:10:36 UTC 2015


On Tue, Jun 09 2015 at  5:21pm -0400,
Mikulas Patocka <mpatocka at redhat.com> wrote:

> This patch makes it possible to use precise timestamps with nanosecond
> granularity in dm statistics.
> 
> Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>
> 
> ---
>  Documentation/device-mapper/statistics.txt |   25 ++++-
>  drivers/md/dm-stats.c                      |  139 +++++++++++++++++++++--------
>  drivers/md/dm-stats.h                      |    4 
>  3 files changed, 125 insertions(+), 43 deletions(-)
> 
> Index: linux-4.1-rc7/drivers/md/dm-stats.c
> ===================================================================
> --- linux-4.1-rc7.orig/drivers/md/dm-stats.c	2015-06-08 16:02:27.000000000 +0200
> +++ linux-4.1-rc7/drivers/md/dm-stats.c	2015-06-08 16:38:43.000000000 +0200
> @@ -33,13 +33,14 @@ struct dm_stat_percpu {
>  
>  struct dm_stat_shared {
>  	atomic_t in_flight[2];
> -	unsigned long stamp;
> +	unsigned long long stamp;
>  	struct dm_stat_percpu tmp;
>  };
>  
>  struct dm_stat {
>  	struct list_head list_entry;
>  	int id;
> +	unsigned stat_flags;
>  	size_t n_entries;
>  	sector_t start;
>  	sector_t end;
> @@ -53,6 +54,8 @@ struct dm_stat {
>  	struct dm_stat_shared stat_shared[0];
>  };
>  
> +#define STAT_PRECISE_TIMESTAMPS		1
> +
>  struct dm_stats_last_position {
>  	sector_t last_sector;
>  	unsigned last_rw;
> @@ -227,7 +230,8 @@ void dm_stats_cleanup(struct dm_stats *s
>  }
>  
>  static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
> -			   sector_t step, const char *program_id, const char *aux_data,
> +			   sector_t step, unsigned stat_flags,
> +			   const char *program_id, const char *aux_data,
>  			   void (*suspend_callback)(struct mapped_device *),
>  			   void (*resume_callback)(struct mapped_device *),
>  			   struct mapped_device *md)
> @@ -268,6 +272,7 @@ static int dm_stats_create(struct dm_sta
>  	if (!s)
>  		return -ENOMEM;
>  
> +	s->stat_flags = stat_flags;
>  	s->n_entries = n_entries;
>  	s->start = start;
>  	s->end = end;
> @@ -417,15 +422,22 @@ static int dm_stats_list(struct dm_stats
>  	return 1;
>  }
>  
> -static void dm_stat_round(struct dm_stat_shared *shared, struct dm_stat_percpu *p)
> +static void dm_stat_round(struct dm_stat *s, struct dm_stat_shared *shared,
> +			  struct dm_stat_percpu *p)
>  {
>  	/*
>  	 * This is racy, but so is part_round_stats_single.
>  	 */
> -	unsigned long now = jiffies;
> -	unsigned in_flight_read;
> -	unsigned in_flight_write;
> -	unsigned long difference = now - shared->stamp;
> +	unsigned long long now, difference;
> +	unsigned in_flight_read, in_flight_write;
> +
> +	if (likely(!(s->stat_flags & STAT_PRECISE_TIMESTAMPS))) {
> +		now = jiffies;
> +	} else {
> +		now = ktime_to_ns(ktime_get());
> +	}
> +
> +	difference = now - shared->stamp;
>  
>  	if (!difference)
>  		return;

Here 'difference' is in nanosecond resolution if STAT_PRECISE_TIMESTAMPS

> @@ -646,11 +673,15 @@ static int dm_stats_clear(struct dm_stat
>  /*
>   * This is like jiffies_to_msec, but works for 64-bit values.
>   */
> -static unsigned long long dm_jiffies_to_msec64(unsigned long long j)
> +static unsigned long long dm_jiffies_to_msec64(struct dm_stat *s, unsigned long long j)
>  {
> -	unsigned long long result = 0;
> +	unsigned long long result;
>  	unsigned mult;
>  
> +	if (s->stat_flags & STAT_PRECISE_TIMESTAMPS)
> +		return j;
> +
> +	result = 0;
>  	if (j)
>  		result = jiffies_to_msecs(j & 0x3fffff);
>  	if (j >= 1 << 22) {

Yet here you aren't converting ns to ms...

> @@ -712,16 +743,16 @@ static int dm_stats_print(struct dm_stat
>  		       shared->tmp.ios[READ],
>  		       shared->tmp.merges[READ],
>  		       shared->tmp.sectors[READ],
> -		       dm_jiffies_to_msec64(shared->tmp.ticks[READ]),
> +		       dm_jiffies_to_msec64(s, shared->tmp.ticks[READ]),
>  		       shared->tmp.ios[WRITE],
>  		       shared->tmp.merges[WRITE],
>  		       shared->tmp.sectors[WRITE],
> -		       dm_jiffies_to_msec64(shared->tmp.ticks[WRITE]),
> +		       dm_jiffies_to_msec64(s, shared->tmp.ticks[WRITE]),
>  		       dm_stat_in_flight(shared),
> -		       dm_jiffies_to_msec64(shared->tmp.io_ticks_total),
> -		       dm_jiffies_to_msec64(shared->tmp.time_in_queue),
> -		       dm_jiffies_to_msec64(shared->tmp.io_ticks[READ]),
> -		       dm_jiffies_to_msec64(shared->tmp.io_ticks[WRITE]));
> +		       dm_jiffies_to_msec64(s, shared->tmp.io_ticks_total),
> +		       dm_jiffies_to_msec64(s, shared->tmp.time_in_queue),
> +		       dm_jiffies_to_msec64(s, shared->tmp.io_ticks[READ]),
> +		       dm_jiffies_to_msec64(s, shared->tmp.io_ticks[WRITE]));
>  
>  		if (unlikely(sz + 1 >= maxlen))
>  			goto buffer_overflow;

So the printed stats won't actually be in msec.

Or am I missing something?




More information about the dm-devel mailing list