Option for changing log files to use Unix epoch instead of being
[fio.git] / stat.c
diff --git a/stat.c b/stat.c
index 7a35117a6f1998faae15cae2c1e3b660205470b7..552d88dde06797c9098820da224cd0891aab268e 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -257,13 +257,13 @@ out:
                free(ovals);
 }
 
-int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
-            double *mean, double *dev)
+bool calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
+             double *mean, double *dev)
 {
        double n = (double) is->samples;
 
        if (n == 0)
-               return 0;
+               return false;
 
        *min = is->min_val;
        *max = is->max_val;
@@ -274,7 +274,7 @@ int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
        else
                *dev = 0;
 
-       return 1;
+       return true;
 }
 
 void show_group_stats(struct group_run_stats *rs, struct buf_output *out)
@@ -364,7 +364,7 @@ static void display_lat(const char *name, unsigned long min, unsigned long max,
        const char *base = "(usec)";
        char *minp, *maxp;
 
-       if (!usec_to_msec(&min, &max, &mean, &dev))
+       if (usec_to_msec(&min, &max, &mean, &dev))
                base = "(msec)";
 
        minp = num2str(min, 6, 1, 0, 0);
@@ -1090,8 +1090,8 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts,
        log_buf(out, "\n");
 }
 
-void json_add_job_opts(struct json_object *root, const char *name,
-                      struct flist_head *opt_list, bool num_jobs)
+static void json_add_job_opts(struct json_object *root, const char *name,
+                             struct flist_head *opt_list, bool num_jobs)
 {
        struct json_object *dir_object;
        struct flist_head *entry;
@@ -1965,6 +1965,7 @@ void regrow_logs(struct thread_data *td)
 {
        regrow_log(td->slat_log);
        regrow_log(td->clat_log);
+       regrow_log(td->clat_hist_log);
        regrow_log(td->lat_log);
        regrow_log(td->bw_log);
        regrow_log(td->iops_log);
@@ -2019,7 +2020,7 @@ static void __add_log_sample(struct io_log *iolog, unsigned long val,
                s = get_sample(iolog, cur_log, cur_log->nr_samples);
 
                s->val = val;
-               s->time = t;
+               s->time = t + iolog->td->unix_epoch;
                io_sample_set_ddir(iolog, s, ddir);
                s->bs = bs;
 
@@ -2139,7 +2140,9 @@ static long add_log_sample(struct thread_data *td, struct io_log *iolog,
         * need to do.
         */
        this_window = elapsed - iolog->avg_last;
-       if (this_window < iolog->avg_msec) {
+       if (elapsed < iolog->avg_last)
+               return iolog->avg_last - elapsed;
+       else if (this_window < iolog->avg_msec) {
                int diff = iolog->avg_msec - this_window;
 
                if (inline_log(iolog) || diff > LOG_MSEC_SLACK)
@@ -2193,7 +2196,9 @@ static void add_clat_percentile_sample(struct thread_stat *ts,
 void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
                     unsigned long usec, unsigned int bs, uint64_t offset)
 {
+       unsigned long elapsed, this_window;
        struct thread_stat *ts = &td->ts;
+       struct io_log *iolog = td->clat_hist_log;
 
        td_io_u_lock(td);
 
@@ -2205,6 +2210,44 @@ void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
        if (ts->clat_percentiles)
                add_clat_percentile_sample(ts, usec, ddir);
 
+       if (iolog && iolog->hist_msec) {
+               struct io_hist *hw = &iolog->hist_window[ddir];
+
+               hw->samples++;
+               elapsed = mtime_since_now(&td->epoch);
+               if (!hw->hist_last)
+                       hw->hist_last = elapsed;
+               this_window = elapsed - hw->hist_last;
+               
+               if (this_window >= iolog->hist_msec) {
+                       unsigned int *io_u_plat;
+                       struct io_u_plat_entry *dst;
+
+                       /*
+                        * Make a byte-for-byte copy of the latency histogram
+                        * stored in td->ts.io_u_plat[ddir], recording it in a
+                        * log sample. Note that the matching call to free() is
+                        * located in iolog.c after printing this sample to the
+                        * log file.
+                        */
+                       io_u_plat = (unsigned int *) td->ts.io_u_plat[ddir];
+                       dst = malloc(sizeof(struct io_u_plat_entry));
+                       memcpy(&(dst->io_u_plat), io_u_plat,
+                               FIO_IO_U_PLAT_NR * sizeof(unsigned int));
+                       flist_add(&dst->list, &hw->list);
+                       __add_log_sample(iolog, (unsigned long)dst, ddir, bs,
+                                               elapsed, offset);
+
+                       /*
+                        * Update the last time we recorded as being now, minus
+                        * any drift in time we encountered before actually
+                        * making the record.
+                        */
+                       hw->hist_last = elapsed - (this_window - iolog->hist_msec);
+                       hw->samples = 0;
+               }
+       }
+
        td_io_u_unlock(td);
 }