t/io_uring: fix bandwidth calculation
[fio.git] / eta.c
diff --git a/eta.c b/eta.c
index 3126f217d490ba27e05abe65394be285354f77a2..ea1781f3b792147636210f38714abb089870a2da 100644 (file)
--- a/eta.c
+++ b/eta.c
@@ -2,7 +2,6 @@
  * Status and ETA code
  */
 #include <unistd.h>
-#include <fcntl.h>
 #include <string.h>
 #ifdef CONFIG_VALGRIND_DEV
 #include <valgrind/drd.h>
@@ -150,7 +149,7 @@ void eta_to_str(char *str, unsigned long eta_sec)
                str += sprintf(str, "%02uh:", h);
 
        str += sprintf(str, "%02um:", m);
-       str += sprintf(str, "%02us", s);
+       sprintf(str, "%02us", s);
 }
 
 /*
@@ -178,12 +177,27 @@ static unsigned long thread_eta(struct thread_data *td)
                bytes_total = td->fill_device_size;
        }
 
-       if (td->o.zone_size && td->o.zone_skip && bytes_total) {
+       /*
+        * If io_size is set, bytes_total is an exact value that does not need
+        * adjustment.
+        */
+       if (td->o.zone_size && td->o.zone_skip && bytes_total &&
+           !fio_option_is_set(&td->o, io_size)) {
                unsigned int nr_zones;
                uint64_t zone_bytes;
 
-               zone_bytes = bytes_total + td->o.zone_size + td->o.zone_skip;
-               nr_zones = (zone_bytes - 1) / (td->o.zone_size + td->o.zone_skip);
+               /*
+                * Calculate the upper bound of the number of zones that will
+                * be processed, including skipped bytes between zones. If this
+                * is larger than total_io_size (e.g. when --io_size or --size
+                * specify a small value), use the lower bound to avoid
+                * adjustments to a negative value that would result in a very
+                * large bytes_total and an incorrect eta.
+                */
+               zone_bytes = td->o.zone_size + td->o.zone_skip;
+               nr_zones = (bytes_total + zone_bytes - 1) / zone_bytes;
+               if (bytes_total < nr_zones * td->o.zone_skip)
+                       nr_zones = bytes_total / zone_bytes;
                bytes_total -= nr_zones * td->o.zone_skip;
        }
 
@@ -317,7 +331,7 @@ static void calc_rate(int unified_rw_rep, unsigned long mtime,
                else
                        this_rate = 0;
 
-               if (unified_rw_rep) {
+               if (unified_rw_rep == UNIFIED_MIXED) {
                        rate[i] = 0;
                        rate[0] += this_rate;
                } else
@@ -342,7 +356,7 @@ static void calc_iops(int unified_rw_rep, unsigned long mtime,
                else
                        this_iops = 0;
 
-               if (unified_rw_rep) {
+               if (unified_rw_rep == UNIFIED_MIXED) {
                        iops[i] = 0;
                        iops[0] += this_iops;
                } else
@@ -369,8 +383,8 @@ bool calc_thread_status(struct jobs_eta *je, int force)
        struct thread_data *td;
        int i, unified_rw_rep;
        uint64_t rate_time, disp_time, bw_avg_time, *eta_secs;
-       unsigned long long io_bytes[DDIR_RWDIR_CNT];
-       unsigned long long io_iops[DDIR_RWDIR_CNT];
+       unsigned long long io_bytes[DDIR_RWDIR_CNT] = {};
+       unsigned long long io_iops[DDIR_RWDIR_CNT] = {};
        struct timespec now;
 
        static unsigned long long rate_io_bytes[DDIR_RWDIR_CNT];
@@ -399,8 +413,6 @@ bool calc_thread_status(struct jobs_eta *je, int force)
 
        je->elapsed_sec = (mtime_since_genesis() + 999) / 1000;
 
-       io_bytes[DDIR_READ] = io_bytes[DDIR_WRITE] = io_bytes[DDIR_TRIM] = 0;
-       io_iops[DDIR_READ] = io_iops[DDIR_WRITE] = io_iops[DDIR_TRIM] = 0;
        bw_avg_time = ULONG_MAX;
        unified_rw_rep = 0;
        for_each_td(td, i) {
@@ -495,9 +507,10 @@ bool calc_thread_status(struct jobs_eta *je, int force)
                calc_rate(unified_rw_rep, rate_time, io_bytes, rate_io_bytes,
                                je->rate);
                memcpy(&rate_prev_time, &now, sizeof(now));
-               add_agg_sample(sample_val(je->rate[DDIR_READ]), DDIR_READ, 0);
-               add_agg_sample(sample_val(je->rate[DDIR_WRITE]), DDIR_WRITE, 0);
-               add_agg_sample(sample_val(je->rate[DDIR_TRIM]), DDIR_TRIM, 0);
+               regrow_agg_logs();
+               for_each_rw_ddir(ddir) {
+                       add_agg_sample(sample_val(je->rate[ddir]), ddir, 0);
+               }
        }
 
        disp_time = mtime_since(&disp_prev_time, &now);
@@ -519,6 +532,45 @@ bool calc_thread_status(struct jobs_eta *je, int force)
        return true;
 }
 
+static int gen_eta_str(struct jobs_eta *je, char *p, size_t left,
+                      char **rate_str, char **iops_str)
+{
+       static const char c[DDIR_RWDIR_CNT] = {'r', 'w', 't'};
+       bool has[DDIR_RWDIR_CNT];
+       bool has_any = false;
+       const char *sep;
+       int l = 0;
+
+       for_each_rw_ddir(ddir) {
+               has[ddir] = (je->rate[ddir] || je->iops[ddir]);
+               has_any |= has[ddir];
+       }
+       if (!has_any)
+               return 0;
+
+       l += snprintf(p + l, left - l, "[");
+       sep = "";
+       for_each_rw_ddir(ddir) {
+               if (has[ddir]) {
+                       l += snprintf(p + l, left - l, "%s%c=%s",
+                                       sep, c[ddir], rate_str[ddir]);
+                       sep = ",";
+               }
+       }
+       l += snprintf(p + l, left - l, "][");
+       sep = "";
+       for_each_rw_ddir(ddir) {
+               if (has[ddir]) {
+                       l += snprintf(p + l, left - l, "%s%c=%s",
+                                       sep, c[ddir], iops_str[ddir]);
+                       sep = ",";
+               }
+       }
+       l += snprintf(p + l, left - l, " IOPS]");
+
+       return l;
+}
+
 void display_thread_status(struct jobs_eta *je)
 {
        static struct timespec disp_eta_new_line;
@@ -593,21 +645,10 @@ void display_thread_status(struct jobs_eta *je)
                }
 
                left = sizeof(output) - (p - output) - 1;
+               l = snprintf(p, left, ": [%s][%s]", je->run_str, perc_str);
+               l += gen_eta_str(je, p + l, left - l, rate_str, iops_str);
+               l += snprintf(p + l, left - l, "[eta %s]", eta_str);
 
-               if (je->rate[DDIR_TRIM] || je->iops[DDIR_TRIM])
-                       l = snprintf(p, left,
-                               ": [%s][%s][r=%s,w=%s,t=%s][r=%s,w=%s,t=%s IOPS][eta %s]",
-                               je->run_str, perc_str, rate_str[DDIR_READ],
-                               rate_str[DDIR_WRITE], rate_str[DDIR_TRIM],
-                               iops_str[DDIR_READ], iops_str[DDIR_WRITE],
-                               iops_str[DDIR_TRIM], eta_str);
-               else
-                       l = snprintf(p, left,
-                               ": [%s][%s][r=%s,w=%s][r=%s,w=%s IOPS][eta %s]",
-                               je->run_str, perc_str,
-                               rate_str[DDIR_READ], rate_str[DDIR_WRITE],
-                               iops_str[DDIR_READ], iops_str[DDIR_WRITE],
-                               eta_str);
                /* If truncation occurred adjust l so p is on the null */
                if (l >= left)
                        l = left - 1;
@@ -622,7 +663,7 @@ void display_thread_status(struct jobs_eta *je)
                        free(iops_str[ddir]);
                }
        }
-       p += sprintf(p, "\r");
+       sprintf(p, "\r");
 
        printf("%s", output);
 
@@ -673,6 +714,10 @@ void print_thread_status(void)
 
 void print_status_init(int thr_number)
 {
+       struct jobs_eta_packed jep;
+
+       compiletime_assert(sizeof(struct jobs_eta) == sizeof(jep), "jobs_eta");
+
        DRD_IGNORE_VAR(__run_str);
        __run_str[thr_number] = 'P';
        update_condensed_str(__run_str, run_str);