Merge branch 'samples-colnames' of https://github.com/parallel-fs-utils/fio
[fio.git] / stat.c
diff --git a/stat.c b/stat.c
index 8de48354b7715f97064ba9f3947fd9baf4d79e95..ef9c4af2d81878a1ec6ec427cc804c18f7b07752 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -14,6 +14,7 @@
 #include "lib/output_buffer.h"
 #include "helper_thread.h"
 #include "smalloc.h"
+#include "zbd.h"
 
 #define LOG_MSEC_SLACK 1
 
@@ -419,7 +420,7 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts,
        unsigned long runt;
        unsigned long long min, max, bw, iops;
        double mean, dev;
-       char *io_p, *bw_p, *bw_p_alt, *iops_p;
+       char *io_p, *bw_p, *bw_p_alt, *iops_p, *zbd_w_st = NULL;
        int i2p;
 
        if (ddir_sync(ddir)) {
@@ -450,12 +451,16 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts,
 
        iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt;
        iops_p = num2str(iops, ts->sig_figs, 1, 0, N2S_NONE);
+       if (ddir == DDIR_WRITE)
+               zbd_w_st = zbd_write_status(ts);
 
-       log_buf(out, "  %s: IOPS=%s, BW=%s (%s)(%s/%llumsec)\n",
+       log_buf(out, "  %s: IOPS=%s, BW=%s (%s)(%s/%llumsec)%s\n",
                        rs->unified_rw_rep ? "mixed" : str[ddir],
                        iops_p, bw_p, bw_p_alt, io_p,
-                       (unsigned long long) ts->runtime[ddir]);
+                       (unsigned long long) ts->runtime[ddir],
+                       zbd_w_st ? : "");
 
+       free(zbd_w_st);
        free(io_p);
        free(bw_p);
        free(bw_p_alt);
@@ -1054,10 +1059,16 @@ static void add_ddir_status_json(struct thread_stat *ts,
 
        if (ts->clat_percentiles || ts->lat_percentiles) {
                if (ddir_rw(ddir)) {
+                       uint64_t samples;
+
+                       if (ts->clat_percentiles)
+                               samples = ts->clat_stat[ddir].samples;
+                       else
+                               samples = ts->lat_stat[ddir].samples;
+
                        len = calc_clat_percentiles(ts->io_u_plat[ddir],
-                                       ts->clat_stat[ddir].samples,
-                                       ts->percentile_list, &ovals, &maxv,
-                                       &minv);
+                                       samples, ts->percentile_list, &ovals,
+                                       &maxv, &minv);
                } else {
                        len = calc_clat_percentiles(ts->io_u_sync_plat,
                                        ts->sync_stat.samples,
@@ -1205,7 +1216,7 @@ static void show_thread_status_terse_all(struct thread_stat *ts,
                log_buf(out, ";%3.2f%%", io_u_lat_m[i]);
 
        /* disk util stats, if any */
-       if (ver >= 3)
+       if (ver >= 3 && is_running_backend())
                show_disk_util(1, NULL, out);
 
        /* Additional output if continue_on_error set - default off*/
@@ -1295,13 +1306,8 @@ static struct json_object *show_thread_status_json(struct thread_stat *ts,
        json_object_add_value_int(root, "majf", ts->majf);
        json_object_add_value_int(root, "minf", ts->minf);
 
-
-       /* Calc % distribution of IO depths, usecond, msecond latency */
+       /* Calc % distribution of IO depths */
        stat_calc_dist(ts->io_u_map, ddir_rw_sum(ts->total_io_u), io_u_dist);
-       stat_calc_lat_n(ts, io_u_lat_n);
-       stat_calc_lat_u(ts, io_u_lat_u);
-       stat_calc_lat_m(ts, io_u_lat_m);
-
        tmp = json_create_object();
        json_object_add_value_object(root, "iodepth_level", tmp);
        /* Only show fixed 7 I/O depth levels*/
@@ -1314,6 +1320,44 @@ static struct json_object *show_thread_status_json(struct thread_stat *ts,
                json_object_add_value_float(tmp, (const char *)name, io_u_dist[i]);
        }
 
+       /* Calc % distribution of submit IO depths */
+       stat_calc_dist(ts->io_u_submit, ts->total_submit, io_u_dist);
+       tmp = json_create_object();
+       json_object_add_value_object(root, "iodepth_submit", tmp);
+       /* Only show fixed 7 I/O depth levels*/
+       for (i = 0; i < 7; i++) {
+               char name[20];
+               if (i == 0)
+                       snprintf(name, 20, "0");
+               else if (i < 6)
+                       snprintf(name, 20, "%d", 1 << (i+1));
+               else
+                       snprintf(name, 20, ">=%d", 1 << i);
+               json_object_add_value_float(tmp, (const char *)name, io_u_dist[i]);
+       }
+
+       /* Calc % distribution of completion IO depths */
+       stat_calc_dist(ts->io_u_complete, ts->total_complete, io_u_dist);
+       tmp = json_create_object();
+       json_object_add_value_object(root, "iodepth_complete", tmp);
+       /* Only show fixed 7 I/O depth levels*/
+       for (i = 0; i < 7; i++) {
+               char name[20];
+               if (i == 0)
+                       snprintf(name, 20, "0");
+               else if (i < 6)
+                       snprintf(name, 20, "%d", 1 << (i+1));
+               else
+                       snprintf(name, 20, ">=%d", 1 << i);
+               json_object_add_value_float(tmp, (const char *)name, io_u_dist[i]);
+       }
+
+       /* Calc % distribution of nsecond, usecond, msecond latency */
+       stat_calc_dist(ts->io_u_map, ddir_rw_sum(ts->total_io_u), io_u_dist);
+       stat_calc_lat_n(ts, io_u_lat_n);
+       stat_calc_lat_u(ts, io_u_lat_u);
+       stat_calc_lat_m(ts, io_u_lat_m);
+
        /* Nanosecond latency */
        tmp = json_create_object();
        json_object_add_value_object(root, "latency_ns", tmp);
@@ -1622,6 +1666,7 @@ void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src,
        dst->total_run_time += src->total_run_time;
        dst->total_submit += src->total_submit;
        dst->total_complete += src->total_complete;
+       dst->nr_zone_resets += src->nr_zone_resets;
 }
 
 void init_group_run_stat(struct group_run_stats *gs)
@@ -2302,6 +2347,7 @@ void reset_io_stats(struct thread_data *td)
 
        ts->total_submit = 0;
        ts->total_complete = 0;
+       ts->nr_zone_resets = 0;
 }
 
 static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir,
@@ -2433,11 +2479,13 @@ void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
                     unsigned long long nsec, unsigned long long bs,
                     uint64_t offset)
 {
+       const bool needs_lock = td_async_processing(td);
        unsigned long elapsed, this_window;
        struct thread_stat *ts = &td->ts;
        struct io_log *iolog = td->clat_hist_log;
 
-       td_io_u_lock(td);
+       if (needs_lock)
+               __td_io_u_lock(td);
 
        add_stat_sample(&ts->clat_stat[ddir], nsec);
 
@@ -2486,37 +2534,43 @@ void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
                }
        }
 
-       td_io_u_unlock(td);
+       if (needs_lock)
+               __td_io_u_unlock(td);
 }
 
 void add_slat_sample(struct thread_data *td, enum fio_ddir ddir,
                     unsigned long usec, unsigned long long bs, uint64_t offset)
 {
+       const bool needs_lock = td_async_processing(td);
        struct thread_stat *ts = &td->ts;
 
        if (!ddir_rw(ddir))
                return;
 
-       td_io_u_lock(td);
+       if (needs_lock)
+               __td_io_u_lock(td);
 
        add_stat_sample(&ts->slat_stat[ddir], usec);
 
        if (td->slat_log)
                add_log_sample(td, td->slat_log, sample_val(usec), ddir, bs, offset);
 
-       td_io_u_unlock(td);
+       if (needs_lock)
+               __td_io_u_unlock(td);
 }
 
 void add_lat_sample(struct thread_data *td, enum fio_ddir ddir,
                    unsigned long long nsec, unsigned long long bs,
                    uint64_t offset)
 {
+       const bool needs_lock = td_async_processing(td);
        struct thread_stat *ts = &td->ts;
 
        if (!ddir_rw(ddir))
                return;
 
-       td_io_u_lock(td);
+       if (needs_lock)
+               __td_io_u_lock(td);
 
        add_stat_sample(&ts->lat_stat[ddir], nsec);
 
@@ -2527,12 +2581,14 @@ void add_lat_sample(struct thread_data *td, enum fio_ddir ddir,
        if (ts->lat_percentiles)
                add_clat_percentile_sample(ts, nsec, ddir);
 
-       td_io_u_unlock(td);
+       if (needs_lock)
+               __td_io_u_unlock(td);
 }
 
 void add_bw_sample(struct thread_data *td, struct io_u *io_u,
                   unsigned int bytes, unsigned long long spent)
 {
+       const bool needs_lock = td_async_processing(td);
        struct thread_stat *ts = &td->ts;
        unsigned long rate;
 
@@ -2541,7 +2597,8 @@ void add_bw_sample(struct thread_data *td, struct io_u *io_u,
        else
                rate = 0;
 
-       td_io_u_lock(td);
+       if (needs_lock)
+               __td_io_u_lock(td);
 
        add_stat_sample(&ts->bw_stat[io_u->ddir], rate);
 
@@ -2550,7 +2607,9 @@ void add_bw_sample(struct thread_data *td, struct io_u *io_u,
                               bytes, io_u->offset);
 
        td->stat_io_bytes[io_u->ddir] = td->this_io_bytes[io_u->ddir];
-       td_io_u_unlock(td);
+
+       if (needs_lock)
+               __td_io_u_unlock(td);
 }
 
 static int __add_samples(struct thread_data *td, struct timespec *parent_tv,
@@ -2559,6 +2618,7 @@ static int __add_samples(struct thread_data *td, struct timespec *parent_tv,
                         struct io_stat *stat, struct io_log *log,
                         bool is_kb)
 {
+       const bool needs_lock = td_async_processing(td);
        unsigned long spent, rate;
        enum fio_ddir ddir;
        unsigned long next, next_log;
@@ -2569,7 +2629,8 @@ static int __add_samples(struct thread_data *td, struct timespec *parent_tv,
        if (spent < avg_time && avg_time - spent >= LOG_MSEC_SLACK)
                return avg_time - spent;
 
-       td_io_u_lock(td);
+       if (needs_lock)
+               __td_io_u_lock(td);
 
        /*
         * Compute both read and write rates for the interval.
@@ -2606,7 +2667,8 @@ static int __add_samples(struct thread_data *td, struct timespec *parent_tv,
 
        timespec_add_msec(parent_tv, avg_time);
 
-       td_io_u_unlock(td);
+       if (needs_lock)
+               __td_io_u_unlock(td);
 
        if (spent <= avg_time)
                next = avg_time;
@@ -2626,9 +2688,11 @@ static int add_bw_samples(struct thread_data *td, struct timespec *t)
 void add_iops_sample(struct thread_data *td, struct io_u *io_u,
                     unsigned int bytes)
 {
+       const bool needs_lock = td_async_processing(td);
        struct thread_stat *ts = &td->ts;
 
-       td_io_u_lock(td);
+       if (needs_lock)
+               __td_io_u_lock(td);
 
        add_stat_sample(&ts->iops_stat[io_u->ddir], 1);
 
@@ -2637,7 +2701,9 @@ void add_iops_sample(struct thread_data *td, struct io_u *io_u,
                               bytes, io_u->offset);
 
        td->stat_io_blocks[io_u->ddir] = td->this_io_blocks[io_u->ddir];
-       td_io_u_unlock(td);
+
+       if (needs_lock)
+               __td_io_u_unlock(td);
 }
 
 static int add_iops_samples(struct thread_data *td, struct timespec *t)