Add options to have fio latency profile a device
[fio.git] / stat.c
diff --git a/stat.c b/stat.c
index b3861887e2a204b404acb9c043f1c7302a7c32be..5d50ae865a1268865b1831a5147eff1ff00acd59 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -243,15 +243,13 @@ out:
 int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
             double *mean, double *dev)
 {
-       double n = is->samples;
+       double n = (double) is->samples;
 
-       if (is->samples == 0)
+       if (n == 0)
                return 0;
 
        *min = is->min_val;
        *max = is->max_val;
-
-       n = (double) is->samples;
        *mean = is->mean.u.f;
 
        if (n > 1.0)
@@ -499,7 +497,7 @@ static void show_latencies(struct thread_stat *ts)
        show_lat_m(io_u_lat_m);
 }
 
-void show_thread_status(struct thread_stat *ts, struct group_run_stats *rs)
+void show_thread_status_normal(struct thread_stat *ts, struct group_run_stats *rs)
 {
        double usr_cpu, sys_cpu;
        unsigned long runtime;
@@ -588,6 +586,13 @@ void show_thread_status(struct thread_stat *ts, struct group_run_stats *rs)
                                        ts->first_error,
                                        strerror(ts->first_error));
        }
+       if (ts->latency_depth) {
+               log_info("     latency   : target=%llu, window=%llu, percentile=%.2f%%, depth=%u\n",
+                                       (unsigned long long)ts->latency_target,
+                                       (unsigned long long)ts->latency_window,
+                                       ts->latency_percentile.u.f,
+                                       ts->latency_depth);
+       }
 }
 
 static void show_ddir_status_terse(struct thread_stat *ts,
@@ -885,7 +890,8 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts,
                log_info(";%3.2f%%", io_u_lat_m[i]);
 
        /* disk util stats, if any */
-       show_disk_util(1, NULL);
+       if (is_backend)
+               show_disk_util(1, NULL);
 
        /* Additional output if continue_on_error set - default off*/
        if (ts->continue_on_error)
@@ -972,7 +978,14 @@ static struct json_object *show_thread_status_json(struct thread_stat *ts,
        /* Additional output if continue_on_error set - default off*/
        if (ts->continue_on_error) {
                json_object_add_value_int(root, "total_err", ts->total_err_count);
-               json_object_add_value_int(root, "total_err", ts->first_error);
+               json_object_add_value_int(root, "first_error", ts->first_error);
+       }
+
+       if (ts->latency_depth) {
+               json_object_add_value_int(root, "latency_depth", ts->latency_depth);
+               json_object_add_value_int(root, "latency_target", ts->latency_target);
+               json_object_add_value_float(root, "latency_percentile", ts->latency_percentile.u.f);
+               json_object_add_value_int(root, "latency_window", ts->latency_window);
        }
 
        /* Additional output if description is set */
@@ -993,6 +1006,18 @@ static void show_thread_status_terse(struct thread_stat *ts,
                log_err("fio: bad terse version!? %d\n", terse_version);
 }
 
+struct json_object *show_thread_status(struct thread_stat *ts,
+                                      struct group_run_stats *rs)
+{
+       if (output_format == FIO_OUTPUT_TERSE)
+               show_thread_status_terse(ts, rs);
+       else if (output_format == FIO_OUTPUT_JSON)
+               return(show_thread_status_json(ts, rs));
+       else
+               show_thread_status_normal(ts, rs);
+       return NULL;
+}
+
 static void sum_stat(struct io_stat *dst, struct io_stat *src, int nr)
 {
        double mean, S;
@@ -1253,6 +1278,11 @@ static void __show_run_stats(void)
                        }
                }
 
+               ts->latency_depth = td->latency_qd;
+               ts->latency_target = td->o.latency_target;
+               ts->latency_percentile = td->o.latency_percentile;
+               ts->latency_window = td->o.latency_window;
+
                sum_thread_stats(ts, &td->ts, idx);
        }
 
@@ -1326,7 +1356,7 @@ static void __show_run_stats(void)
                        struct json_object *tmp = show_thread_status_json(ts, rs);
                        json_array_add_value_object(array, tmp);
                } else
-                       show_thread_status(ts, rs);
+                       show_thread_status_normal(ts, rs);
        }
        if (output_format == FIO_OUTPUT_JSON) {
                /* disk util stats, if any */
@@ -1445,11 +1475,21 @@ static struct timeval status_time;
 static int check_status_file(void)
 {
        struct stat sb;
+       const char *temp_dir;
+       char fio_status_file_path[PATH_MAX];
+
+       temp_dir = getenv("TMPDIR");
+       if (temp_dir == NULL)
+               temp_dir = getenv("TEMP");
+       if (temp_dir == NULL)
+               temp_dir = "/tmp";
+
+       snprintf(fio_status_file_path, sizeof(fio_status_file_path), "%s/%s", temp_dir, FIO_STATUS_FILE);
 
-       if (stat(FIO_STATUS_FILE, &sb))
+       if (stat(fio_status_file_path, &sb))
                return 0;
 
-       unlink(FIO_STATUS_FILE);
+       unlink(fio_status_file_path);
        return 1;
 }
 
@@ -1496,13 +1536,23 @@ static void __add_log_sample(struct io_log *iolog, unsigned long val,
 {
        const int nr_samples = iolog->nr_samples;
 
+       if (iolog->disabled)
+               return;
+
        if (!iolog->nr_samples)
                iolog->avg_last = t;
 
        if (iolog->nr_samples == iolog->max_samples) {
                int new_size = sizeof(struct io_sample) * iolog->max_samples*2;
+               void *new_log;
 
-               iolog->log = realloc(iolog->log, new_size);
+               new_log = realloc(iolog->log, new_size);
+               if (!new_log) {
+                       log_err("fio: failed extending iolog! Will stop logging.\n");
+                       iolog->disabled = 1;
+                       return;
+               }
+               iolog->log = new_log;
                iolog->max_samples <<= 1;
        }
 
@@ -1683,7 +1733,7 @@ void add_bw_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs,
        fio_gettime(&td->bw_sample_time, NULL);
 }
 
-void add_iops_sample(struct thread_data *td, enum fio_ddir ddir,
+void add_iops_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs,
                     struct timeval *t)
 {
        struct thread_stat *ts = &td->ts;
@@ -1710,7 +1760,7 @@ void add_iops_sample(struct thread_data *td, enum fio_ddir ddir,
                add_stat_sample(&ts->iops_stat[ddir], iops);
 
                if (td->iops_log)
-                       add_log_sample(td, td->iops_log, iops, ddir, 0);
+                       add_log_sample(td, td->iops_log, iops, ddir, bs);
 
                td->stat_io_blocks[ddir] = td->this_io_blocks[ddir];
        }