dm: requeue IO if mapping table not yet available
[platform/kernel/linux-rpi.git] / drivers / md / dm-stats.c
index 35d368c..0e039a8 100644 (file)
@@ -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;
                }