init: make sure that compression enables refill buffers
[fio.git] / init.c
diff --git a/init.c b/init.c
index b4b09743f1c94225f48a5566462be84ddb27c810..736c6ff83656849c94a4dec8ae2781be4079e0bd 100644 (file)
--- a/init.c
+++ b/init.c
@@ -361,7 +361,7 @@ static int setup_thread_area(void)
 #endif
 
        memset(threads, 0, max_jobs * sizeof(struct thread_data));
-       fio_debug_jobp = (void *) threads + max_jobs * sizeof(struct thread_data);
+       fio_debug_jobp = (unsigned int *)(threads + max_jobs);
        *fio_debug_jobp = -1;
 
        flow_init();
@@ -459,6 +459,7 @@ static struct thread_data *get_new_job(bool global, struct thread_data *parent,
                copy_opt_list(td, parent);
 
        td->io_ops = NULL;
+       td->io_ops_init = 0;
        if (!preserve_eo)
                td->eo = NULL;
 
@@ -522,7 +523,7 @@ static int __setup_rate(struct thread_data *td, enum fio_ddir ddir)
 
        td->rate_next_io_time[ddir] = 0;
        td->rate_io_issue_bytes[ddir] = 0;
-       td->last_usec = 0;
+       td->last_usec[ddir] = 0;
        return 0;
 }
 
@@ -697,6 +698,23 @@ static int fixup_options(struct thread_data *td)
        if (o->iodepth_batch_complete_min > o->iodepth_batch_complete_max)
                o->iodepth_batch_complete_max = o->iodepth_batch_complete_min;
 
+       /*
+        * There's no need to check for in-flight overlapping IOs if the job
+        * isn't changing data or the maximum iodepth is guaranteed to be 1
+        */
+       if (o->serialize_overlap && !(td->flags & TD_F_READ_IOLOG) &&
+           (!(td_write(td) || td_trim(td)) || o->iodepth == 1))
+               o->serialize_overlap = 0;
+       /*
+        * Currently can't check for overlaps in offload mode
+        */
+       if (o->serialize_overlap && o->io_submit_mode == IO_MODE_OFFLOAD) {
+               log_err("fio: checking for in-flight overlaps when the "
+                       "io_submit_mode is offload is not supported\n");
+               o->serialize_overlap = 0;
+               ret = warnings_fatal;
+       }
+
        if (o->nr_files > td->files_index)
                o->nr_files = td->files_index;
 
@@ -730,13 +748,30 @@ static int fixup_options(struct thread_data *td)
                o->size = -1ULL;
 
        if (o->verify != VERIFY_NONE) {
-               if (td_write(td) && o->do_verify && o->numjobs > 1) {
-                       log_info("Multiple writers may overwrite blocks that "
-                               "belong to other jobs. This can cause "
+               if (td_write(td) && o->do_verify && o->numjobs > 1 &&
+                   (o->filename ||
+                    !(o->unique_filename &&
+                      strstr(o->filename_format, "$jobname") &&
+                      strstr(o->filename_format, "$jobnum") &&
+                      strstr(o->filename_format, "$filenum")))) {
+                       log_info("fio: multiple writers may overwrite blocks "
+                               "that belong to other jobs. This can cause "
                                "verification failures.\n");
                        ret = warnings_fatal;
                }
 
+               /*
+                * Warn if verification is requested but no verification of any
+                * kind can be started due to time constraints
+                */
+               if (td_write(td) && o->do_verify && o->timeout &&
+                   o->time_based && !td_read(td) && !o->verify_backlog) {
+                       log_info("fio: verification read phase will never "
+                                "start because write phase uses all of "
+                                "runtime\n");
+                       ret = warnings_fatal;
+               }
+
                if (!fio_option_is_set(o, refill_buffers))
                        o->refill_buffers = 1;
 
@@ -764,11 +799,8 @@ static int fixup_options(struct thread_data *td)
        }
 
        if (o->pre_read) {
-               if (o->invalidate_cache) {
-                       log_info("fio: ignore invalidate option for %s\n",
-                                o->name);
+               if (o->invalidate_cache)
                        o->invalidate_cache = 0;
-               }
                if (td_ioengine_flagged(td, FIO_PIPEIO)) {
                        log_info("fio: cannot pre-read files with an IO engine"
                                 " that isn't seekable. Pre-read disabled.\n");
@@ -783,6 +815,11 @@ static int fixup_options(struct thread_data *td)
                        o->unit_base = 8;
        }
 
+#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()"
@@ -800,7 +837,7 @@ static int fixup_options(struct thread_data *td)
         * Windows doesn't support O_DIRECT or O_SYNC with the _open interface,
         * so fail if we're passed those flags
         */
-       if (td_ioengine_flagged(td, FIO_SYNCIO) && (td->o.odirect || td->o.sync_io)) {
+       if (td_ioengine_flagged(td, FIO_SYNCIO) && (o->odirect || o->sync_io)) {
                log_err("fio: Windows does not support direct or non-buffered io with"
                                " the synchronous ioengines. Use the 'windowsaio' ioengine"
                                " with 'direct=1' and 'iodepth=1' instead.\n");
@@ -818,16 +855,18 @@ static int fixup_options(struct thread_data *td)
                if (o->compress_percentage == 100) {
                        o->zero_buffers = 1;
                        o->compress_percentage = 0;
-               } else if (!fio_option_is_set(o, refill_buffers))
+               } else if (!fio_option_is_set(o, refill_buffers)) {
                        o->refill_buffers = 1;
+                       td->flags |= TD_F_REFILL_BUFFERS;
+               }
        }
 
        /*
         * Using a non-uniform random distribution excludes usage of
         * a random map
         */
-       if (td->o.random_distribution != FIO_RAND_DIST_RANDOM)
-               td->o.norandommap = 1;
+       if (o->random_distribution != FIO_RAND_DIST_RANDOM)
+               o->norandommap = 1;
 
        /*
         * If size is set but less than the min block size, complain
@@ -841,16 +880,16 @@ static int fixup_options(struct thread_data *td)
        /*
         * O_ATOMIC implies O_DIRECT
         */
-       if (td->o.oatomic)
-               td->o.odirect = 1;
+       if (o->oatomic)
+               o->odirect = 1;
 
        /*
         * If randseed is set, that overrides randrepeat
         */
-       if (fio_option_is_set(&td->o, rand_seed))
-               td->o.rand_repeatable = 0;
+       if (fio_option_is_set(o, rand_seed))
+               o->rand_repeatable = 0;
 
-       if (td_ioengine_flagged(td, FIO_NOEXTEND) && td->o.file_append) {
+       if (td_ioengine_flagged(td, FIO_NOEXTEND) && o->file_append) {
                log_err("fio: can't append/extent with IO engine %s\n", td->io_ops->name);
                ret = 1;
        }
@@ -865,28 +904,28 @@ static int fixup_options(struct thread_data *td)
        if (!td->loops)
                td->loops = 1;
 
-       if (td->o.block_error_hist && td->o.nr_files != 1) {
+       if (o->block_error_hist && o->nr_files != 1) {
                log_err("fio: block error histogram only available "
                        "with a single file per job, but %d files "
-                       "provided\n", td->o.nr_files);
+                       "provided\n", o->nr_files);
                ret = 1;
        }
 
-       return ret;
-}
-
-/* External engines are specified by "external:name.o") */
-static const char *get_engine_name(const char *str)
-{
-       char *p = strstr(str, ":");
-
-       if (!p)
-               return str;
+       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;
+       }
 
-       p++;
-       strip_blank_front(&p);
-       strip_blank_end(p);
-       return p;
+       return ret;
 }
 
 static void init_rand_file_service(struct thread_data *td)
@@ -911,9 +950,9 @@ void td_fill_verify_state_seed(struct thread_data *td)
        bool use64;
 
        if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64)
-               use64 = 1;
+               use64 = true;
        else
-               use64 = 0;
+               use64 = false;
 
        init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF],
                use64);
@@ -923,7 +962,22 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64)
 {
        int i;
 
-       init_rand_seed(&td->bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF], use64);
+       /*
+        * trimwrite is special in that we need to generate the same
+        * offsets to get the "write after trim" effect. If we are
+        * using bssplit to set buffer length distributions, ensure that
+        * we seed the trim and write generators identically.
+        */
+       if (td_trimwrite(td)) {
+               init_rand_seed(&td->bsrange_state[DDIR_READ], td->rand_seeds[FIO_RAND_BS_OFF], use64);
+               init_rand_seed(&td->bsrange_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_BS1_OFF], use64);
+               init_rand_seed(&td->bsrange_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_BS1_OFF], use64);
+       } else {
+               init_rand_seed(&td->bsrange_state[DDIR_READ], td->rand_seeds[FIO_RAND_BS_OFF], use64);
+               init_rand_seed(&td->bsrange_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_BS1_OFF], use64);
+               init_rand_seed(&td->bsrange_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_BS2_OFF], use64);
+       }
+
        td_fill_verify_state_seed(td);
        init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF], false);
 
@@ -935,7 +989,9 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64)
        init_rand_seed(&td->file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF], use64);
        init_rand_seed(&td->trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF], use64);
        init_rand_seed(&td->delay_state, td->rand_seeds[FIO_RAND_START_DELAY], use64);
-       init_rand_seed(&td->poisson_state, td->rand_seeds[FIO_RAND_POISSON_OFF], 0);
+       init_rand_seed(&td->poisson_state[0], td->rand_seeds[FIO_RAND_POISSON_OFF], 0);
+       init_rand_seed(&td->poisson_state[1], td->rand_seeds[FIO_RAND_POISSON2_OFF], 0);
+       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);
 
@@ -967,9 +1023,9 @@ void td_fill_rand_seeds(struct thread_data *td)
        }
 
        if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64)
-               use64 = 1;
+               use64 = true;
        else
-               use64 = 0;
+               use64 = false;
 
        td_fill_rand_seeds_internal(td, use64);
 
@@ -983,22 +1039,27 @@ void td_fill_rand_seeds(struct thread_data *td)
  */
 int ioengine_load(struct thread_data *td)
 {
-       const char *engine;
-
-       /*
-        * Engine has already been loaded.
-        */
-       if (td->io_ops)
-               return 0;
        if (!td->o.ioengine) {
                log_err("fio: internal fault, no IO engine specified\n");
                return 1;
        }
 
-       engine = get_engine_name(td->o.ioengine);
-       td->io_ops = load_ioengine(td, engine);
+       if (td->io_ops) {
+               /* An engine is loaded, but the requested ioengine
+                * may have changed.
+                */
+               if (!strcmp(td->io_ops->name, td->o.ioengine)) {
+                       /* The right engine is already loaded */
+                       return 0;
+               }
+
+               /* Unload the old engine. */
+               free_ioengine(td);
+       }
+
+       td->io_ops = load_ioengine(td);
        if (!td->io_ops) {
-               log_err("fio: failed to load engine %s\n", engine);
+               log_err("fio: failed to load engine\n");
                return 1;
        }
 
@@ -1070,6 +1131,9 @@ static void init_flags(struct thread_data *td)
 
        if (o->verify_async || o->io_submit_mode == IO_MODE_OFFLOAD)
                td->flags |= TD_F_NEED_LOCK;
+
+       if (o->mem_type == MEM_CUDA_MALLOC)
+               td->flags &= ~TD_F_SCRAMBLE_BUFFERS;
 }
 
 static int setup_random_seeds(struct thread_data *td)
@@ -1077,8 +1141,12 @@ static int setup_random_seeds(struct thread_data *td)
        unsigned long seed;
        unsigned int i;
 
-       if (!td->o.rand_repeatable && !fio_option_is_set(&td->o, rand_seed))
-               return init_random_state(td, td->rand_seeds, sizeof(td->rand_seeds));
+       if (!td->o.rand_repeatable && !fio_option_is_set(&td->o, rand_seed)) {
+               int ret = init_random_seeds(td->rand_seeds, sizeof(td->rand_seeds));
+               if (!ret)
+                       td_fill_rand_seeds(td);
+               return ret;
+       }
 
        seed = td->o.rand_seed;
        for (i = 0; i < 4; i++)
@@ -1120,7 +1188,7 @@ static char *make_filename(char *buf, size_t buf_size,struct thread_options *o,
 
        if (!o->filename_format || !strlen(o->filename_format)) {
                sprintf(buf, "%s.%d.%d", jobname, jobnum, filenum);
-               return NULL;
+               return buf;
        }
 
        for (f = &fpre_keywords[0]; f->keyword; f++)
@@ -1349,6 +1417,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
        td->mutex = fio_mutex_init(FIO_MUTEX_LOCKED);
 
        td->ts.clat_percentiles = o->clat_percentiles;
+       td->ts.lat_percentiles = o->lat_percentiles;
        td->ts.percentile_precision = o->percentile_precision;
        memcpy(td->ts.percentile_list, o->percentile_list, sizeof(o->percentile_list));
 
@@ -1357,6 +1426,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
                td->ts.slat_stat[i].min_val = ULONG_MAX;
                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->ddir_seq_nr = o->ddir_seq_nr;
 
@@ -1373,7 +1443,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
        prev_group_jobs++;
 
        if (setup_random_seeds(td)) {
-               td_verror(td, errno, "init_random_state");
+               td_verror(td, errno, "setup_random_seeds");
                goto err;
        }
 
@@ -2014,7 +2084,7 @@ static void usage(const char *name)
        printf("  --version\t\tPrint version info and exit\n");
        printf("  --help\t\tPrint this page\n");
        printf("  --cpuclock-test\tPerform test/validation of CPU clock\n");
-       printf("  --crctest=type\tTest speed of checksum functions\n");
+       printf("  --crctest=[type]\tTest speed of checksum functions\n");
        printf("  --cmdhelp=cmd\t\tPrint command help, \"all\" for all of"
                " them\n");
        printf("  --enghelp=engine\tPrint ioengine help, or list"
@@ -2047,7 +2117,7 @@ static void usage(const char *name)
        printf("  --inflate-log=log\tInflate and output compressed log\n");
 #endif
        printf("  --trigger-file=file\tExecute trigger cmd when file exists\n");
-       printf("  --trigger-timeout=t\tExecute trigger af this time\n");
+       printf("  --trigger-timeout=t\tExecute trigger at this time\n");
        printf("  --trigger=cmd\t\tSet this command as local trigger\n");
        printf("  --trigger-remote=cmd\tSet this command as remote trigger\n");
        printf("  --aux-path=path\tUse this path for fio state generated files\n");
@@ -2396,8 +2466,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                        break;
                case 'V':
                        terse_version = atoi(optarg);
-                       if (!(terse_version == 2 || terse_version == 3 ||
-                            terse_version == 4)) {
+                       if (!(terse_version >= 2 && terse_version <= 5)) {
                                log_err("fio: bad terse version format\n");
                                exit_val = 1;
                                do_exit++;
@@ -2508,7 +2577,6 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                        }
 
                        if (!ret && !strcmp(opt, "ioengine")) {
-                               free_ioengine(td);
                                if (ioengine_load(td)) {
                                        put_job(td);
                                        td = NULL;