t/zbd: Reset all zones before test when max open zones is specified
[fio.git] / init.c
diff --git a/init.c b/init.c
index a2b70c4acb4ba51a7916eda28f90bbcf3cdb10a9..3cd0238b1e2f8cad547191952afae22515bf98a9 100644 (file)
--- a/init.c
+++ b/init.c
@@ -32,6 +32,7 @@
 #include "steadystate.h"
 #include "blktrace.h"
 
+#include "oslib/asprintf.h"
 #include "oslib/getopt.h"
 #include "oslib/strcasestr.h"
 
@@ -563,13 +564,11 @@ static int setup_rate(struct thread_data *td)
 {
        int ret = 0;
 
-       if (td->o.rate[DDIR_READ] || td->o.rate_iops[DDIR_READ])
-               ret = __setup_rate(td, DDIR_READ);
-       if (td->o.rate[DDIR_WRITE] || td->o.rate_iops[DDIR_WRITE])
-               ret |= __setup_rate(td, DDIR_WRITE);
-       if (td->o.rate[DDIR_TRIM] || td->o.rate_iops[DDIR_TRIM])
-               ret |= __setup_rate(td, DDIR_TRIM);
-
+       for_each_rw_ddir(ddir) {
+               if (td->o.rate[ddir] || td->o.rate_iops[ddir]) {
+                       ret |= __setup_rate(td, ddir);
+               }
+       }
        return ret;
 }
 
@@ -661,31 +660,25 @@ static int fixup_options(struct thread_data *td)
        if (td_read(td))
                o->overwrite = 1;
 
-       if (!o->min_bs[DDIR_READ])
-               o->min_bs[DDIR_READ] = o->bs[DDIR_READ];
-       if (!o->max_bs[DDIR_READ])
-               o->max_bs[DDIR_READ] = o->bs[DDIR_READ];
-       if (!o->min_bs[DDIR_WRITE])
-               o->min_bs[DDIR_WRITE] = o->bs[DDIR_WRITE];
-       if (!o->max_bs[DDIR_WRITE])
-               o->max_bs[DDIR_WRITE] = o->bs[DDIR_WRITE];
-       if (!o->min_bs[DDIR_TRIM])
-               o->min_bs[DDIR_TRIM] = o->bs[DDIR_TRIM];
-       if (!o->max_bs[DDIR_TRIM])
-               o->max_bs[DDIR_TRIM] = o->bs[DDIR_TRIM];
-
-       o->rw_min_bs = min(o->min_bs[DDIR_READ], o->min_bs[DDIR_WRITE]);
-       o->rw_min_bs = min(o->min_bs[DDIR_TRIM], o->rw_min_bs);
+       for_each_rw_ddir(ddir) {
+               if (!o->min_bs[ddir])
+                       o->min_bs[ddir] = o->bs[ddir];
+               if (!o->max_bs[ddir])
+                       o->max_bs[ddir] = o->bs[ddir];
+       }
+
+       o->rw_min_bs = -1;
+       for_each_rw_ddir(ddir) {
+               o->rw_min_bs = min(o->rw_min_bs, o->min_bs[ddir]);
+       }
 
        /*
         * For random IO, allow blockalign offset other than min_bs.
         */
-       if (!o->ba[DDIR_READ] || !td_random(td))
-               o->ba[DDIR_READ] = o->min_bs[DDIR_READ];
-       if (!o->ba[DDIR_WRITE] || !td_random(td))
-               o->ba[DDIR_WRITE] = o->min_bs[DDIR_WRITE];
-       if (!o->ba[DDIR_TRIM] || !td_random(td))
-               o->ba[DDIR_TRIM] = o->min_bs[DDIR_TRIM];
+       for_each_rw_ddir(ddir) {
+               if (!o->ba[ddir] || !td_random(td))
+                       o->ba[ddir] = o->min_bs[ddir];
+       }
 
        if ((o->ba[DDIR_READ] != o->min_bs[DDIR_READ] ||
            o->ba[DDIR_WRITE] != o->min_bs[DDIR_WRITE] ||
@@ -764,14 +757,12 @@ static int fixup_options(struct thread_data *td)
                log_err("fio: rate and rate_iops are mutually exclusive\n");
                ret |= 1;
        }
-       if ((o->rate[DDIR_READ] && (o->rate[DDIR_READ] < o->ratemin[DDIR_READ])) ||
-           (o->rate[DDIR_WRITE] && (o->rate[DDIR_WRITE] < o->ratemin[DDIR_WRITE])) ||
-           (o->rate[DDIR_TRIM] && (o->rate[DDIR_TRIM] < o->ratemin[DDIR_TRIM])) ||
-           (o->rate_iops[DDIR_READ] && (o->rate_iops[DDIR_READ] < o->rate_iops_min[DDIR_READ])) ||
-           (o->rate_iops[DDIR_WRITE] && (o->rate_iops[DDIR_WRITE] < o->rate_iops_min[DDIR_WRITE])) ||
-           (o->rate_iops[DDIR_TRIM] && (o->rate_iops[DDIR_TRIM] < o->rate_iops_min[DDIR_TRIM]))) {
-               log_err("fio: minimum rate exceeds rate\n");
-               ret |= 1;
+       for_each_rw_ddir(ddir) {
+               if ((o->rate[ddir] && (o->rate[ddir] < o->ratemin[ddir])) ||
+                   (o->rate_iops[ddir] && (o->rate_iops[ddir] < o->rate_iops_min[ddir]))) {
+                       log_err("fio: minimum rate exceeds rate, ddir %d\n", +ddir);
+                       ret |= 1;
+               }
        }
 
        if (!o->timeout && o->time_based) {
@@ -852,11 +843,6 @@ static int fixup_options(struct thread_data *td)
                        o->unit_base = N2S_BYTEPERSEC;
        }
 
-#ifndef FIO_HAVE_ANY_FALLOCATE
-       /* Platform doesn't support any fallocate so force it to none */
-       o->fallocate_mode = FIO_FALLOCATE_NONE;
-#endif
-
 #ifndef CONFIG_FDATASYNC
        if (o->fdatasync_blocks) {
                log_info("fio: this platform does not support fdatasync()"
@@ -948,31 +934,18 @@ static int fixup_options(struct thread_data *td)
                ret |= 1;
        }
 
-       if (fio_option_is_set(o, clat_percentiles) &&
-           !fio_option_is_set(o, lat_percentiles)) {
-               o->lat_percentiles = !o->clat_percentiles;
-       } else if (fio_option_is_set(o, lat_percentiles) &&
-                  !fio_option_is_set(o, clat_percentiles)) {
-               o->clat_percentiles = !o->lat_percentiles;
-       } else if (fio_option_is_set(o, lat_percentiles) &&
-                  fio_option_is_set(o, clat_percentiles) &&
-                  o->lat_percentiles && o->clat_percentiles) {
-               log_err("fio: lat_percentiles and clat_percentiles are "
-                       "mutually exclusive\n");
-               ret |= 1;
-       }
-
        if (o->disable_lat)
                o->lat_percentiles = 0;
        if (o->disable_clat)
                o->clat_percentiles = 0;
+       if (o->disable_slat)
+               o->slat_percentiles = 0;
 
        /*
         * Fix these up to be nsec internally
         */
        o->max_latency *= 1000ULL;
        o->latency_target *= 1000ULL;
-       o->latency_window *= 1000ULL;
 
        return ret;
 }
@@ -1009,9 +982,9 @@ void td_fill_verify_state_seed(struct thread_data *td)
 
 static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64)
 {
-       unsigned int read_seed = td->rand_seeds[FIO_RAND_BS_OFF];
-       unsigned int write_seed = td->rand_seeds[FIO_RAND_BS1_OFF];
-       unsigned int trim_seed = td->rand_seeds[FIO_RAND_BS2_OFF];
+       uint64_t read_seed = td->rand_seeds[FIO_RAND_BS_OFF];
+       uint64_t write_seed = td->rand_seeds[FIO_RAND_BS1_OFF];
+       uint64_t trim_seed = td->rand_seeds[FIO_RAND_BS2_OFF];
        int i;
 
        /*
@@ -1046,6 +1019,7 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64)
        init_rand_seed(&td->poisson_state[2], td->rand_seeds[FIO_RAND_POISSON3_OFF], 0);
        init_rand_seed(&td->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF], false);
        init_rand_seed(&td->zone_state, td->rand_seeds[FIO_RAND_ZONE_OFF], false);
+       init_rand_seed(&td->prio_state, td->rand_seeds[FIO_RAND_PRIO_CMDS], false);
 
        if (!td_random(td))
                return;
@@ -1115,6 +1089,9 @@ int ioengine_load(struct thread_data *td)
                 */
                dlhandle = td->io_ops_dlhandle;
                ops = load_ioengine(td);
+               if (!ops)
+                       goto fail;
+
                if (ops == td->io_ops && dlhandle == td->io_ops_dlhandle) {
                        if (dlhandle)
                                dlclose(dlhandle);
@@ -1129,10 +1106,8 @@ int ioengine_load(struct thread_data *td)
        }
 
        td->io_ops = load_ioengine(td);
-       if (!td->io_ops) {
-               log_err("fio: failed to load engine\n");
-               return 1;
-       }
+       if (!td->io_ops)
+               goto fail;
 
        if (td->io_ops->option_struct_size && td->io_ops->options) {
                /*
@@ -1171,6 +1146,11 @@ int ioengine_load(struct thread_data *td)
 
        td_set_ioengine_flags(td);
        return 0;
+
+fail:
+       log_err("fio: failed to load engine\n");
+       return 1;
+
 }
 
 static void init_flags(struct thread_data *td)
@@ -1217,7 +1197,7 @@ static void init_flags(struct thread_data *td)
 
 static int setup_random_seeds(struct thread_data *td)
 {
-       unsigned long seed;
+       uint64_t seed;
        unsigned int i;
 
        if (!td->o.rand_repeatable && !fio_option_is_set(&td->o, rand_seed)) {
@@ -1273,8 +1253,7 @@ static char *make_filename(char *buf, size_t buf_size,struct thread_options *o,
        for (f = &fpre_keywords[0]; f->keyword; f++)
                f->strlen = strlen(f->keyword);
 
-       buf[buf_size - 1] = '\0';
-       strncpy(buf, o->filename_format, buf_size - 1);
+       snprintf(buf, buf_size, "%s", o->filename_format);
 
        memset(copy, 0, sizeof(copy));
        for (f = &fpre_keywords[0]; f->keyword; f++) {
@@ -1353,7 +1332,7 @@ static char *make_filename(char *buf, size_t buf_size,struct thread_options *o,
                        if (post_start)
                                strncpy(dst, buf + post_start, dst_left);
 
-                       strncpy(buf, copy, buf_size - 1);
+                       snprintf(buf, buf_size, "%s", copy);
                } while (1);
        }
 
@@ -1438,7 +1417,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                   int recursed, int client_type)
 {
        unsigned int i;
-       char fname[PATH_MAX];
+       char fname[PATH_MAX + 1];
        int numjobs, file_alloced;
        struct thread_options *o = &td->o;
        char logname[PATH_MAX + 32];
@@ -1513,6 +1492,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
 
        td->ts.clat_percentiles = o->clat_percentiles;
        td->ts.lat_percentiles = o->lat_percentiles;
+       td->ts.slat_percentiles = o->slat_percentiles;
        td->ts.percentile_precision = o->percentile_precision;
        memcpy(td->ts.percentile_list, o->percentile_list, sizeof(o->percentile_list));
        td->ts.sig_figs = o->sig_figs;
@@ -1523,6 +1503,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                td->ts.lat_stat[i].min_val = ULONG_MAX;
                td->ts.bw_stat[i].min_val = ULONG_MAX;
                td->ts.iops_stat[i].min_val = ULONG_MAX;
+               td->ts.clat_high_prio_stat[i].min_val = ULONG_MAX;
+               td->ts.clat_low_prio_stat[i].min_val = ULONG_MAX;
        }
        td->ts.sync_stat.min_val = ULONG_MAX;
        td->ddir_seq_nr = o->ddir_seq_nr;
@@ -1753,11 +1735,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                if (file_alloced) {
                        if (td_new->files) {
                                struct fio_file *f;
-                               for_each_file(td_new, f, i) {
-                                       if (f->file_name)
-                                               sfree(f->file_name);
-                                       sfree(f);
-                               }
+                               for_each_file(td_new, f, i)
+                                       fio_file_free(f);
                                free(td_new->files);
                                td_new->files = NULL;
                        }
@@ -1856,6 +1835,7 @@ static int __parse_jobs_ini(struct thread_data *td,
                int nested, char *name, char ***popts, int *aopts, int *nopts)
 {
        bool global = false;
+       bool stdin_occupied = false;
        char *string;
        FILE *f;
        char *p;
@@ -1872,9 +1852,10 @@ static int __parse_jobs_ini(struct thread_data *td,
        if (is_buf)
                f = NULL;
        else {
-               if (!strcmp(file, "-"))
+               if (!strcmp(file, "-")) {
                        f = stdin;
-               else
+                       stdin_occupied = true;
+               } else
                        f = fopen(file, "r");
 
                if (!f) {
@@ -1887,7 +1868,7 @@ static int __parse_jobs_ini(struct thread_data *td,
                }
        }
 
-       string = malloc(4096);
+       string = malloc(OPT_LEN_MAX);
 
        /*
         * it's really 256 + small bit, 280 should suffice
@@ -1920,7 +1901,7 @@ static int __parse_jobs_ini(struct thread_data *td,
                        if (is_buf)
                                p = strsep(&file, "\n");
                        else
-                               p = fgets(string, 4096, f);
+                               p = fgets(string, OPT_LEN_MAX, f);
                        if (!p)
                                break;
                }
@@ -1989,7 +1970,7 @@ static int __parse_jobs_ini(struct thread_data *td,
                                if (is_buf)
                                        p = strsep(&file, "\n");
                                else
-                                       p = fgets(string, 4096, f);
+                                       p = fgets(string, OPT_LEN_MAX, f);
                                if (!p)
                                        break;
                                dprint(FD_PARSE, "%s", p);
@@ -2029,19 +2010,12 @@ static int __parse_jobs_ini(struct thread_data *td,
                                 */
                                if (access(filename, F_OK) &&
                                    (ts = strrchr(file, '/'))) {
-                                       int len = ts - file +
-                                               strlen(filename) + 2;
-
-                                       if (!(full_fn = calloc(1, len))) {
+                                       if (asprintf(&full_fn, "%.*s%s",
+                                                (int)(ts - file + 1), file,
+                                                filename) < 0) {
                                                ret = ENOMEM;
                                                break;
                                        }
-
-                                       strncpy(full_fn,
-                                               file, (ts - file) + 1);
-                                       strncpy(full_fn + (ts - file) + 1,
-                                               filename, strlen(filename));
-                                       full_fn[len - 1] = 0;
                                        filename = full_fn;
                                }
 
@@ -2083,6 +2057,20 @@ static int __parse_jobs_ini(struct thread_data *td,
                }
 
                ret = fio_options_parse(td, opts, num_opts);
+
+               if (!ret && td->o.read_iolog_file != NULL) {
+                       char *fname = get_name_by_idx(td->o.read_iolog_file,
+                                                     td->subjob_number);
+                       if (!strcmp(fname, "-")) {
+                               if (stdin_occupied) {
+                                       log_err("fio: only one user (read_iolog_file/job "
+                                               "file) of stdin is permitted at once but "
+                                               "more than one was found.\n");
+                                       ret = 1;
+                               }
+                               stdin_occupied = true;
+                       }
+               }
                if (!ret) {
                        if (dump_cmdline)
                                dump_opt_list(td);
@@ -2907,6 +2895,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                        log_err("%s: unrecognized option '%s'\n", argv[0],
                                                        argv[optind - 1]);
                        show_closest_option(argv[optind - 1]);
+                       fallthrough;
                default:
                        do_exit++;
                        exit_val = 1;