X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=init.c;h=84325f1e86fc800cdef58140d677004b4eacf9f1;hb=refs%2Fheads%2Fmaster;hp=139351527bebb2abe3037f2f0b09391ef6f36b84;hpb=13f475ad58ff97e5ca0ecd311a6f039f74d51c12;p=fio.git diff --git a/init.c b/init.c index 13935152..ff3e9a90 100644 --- a/init.c +++ b/init.c @@ -618,6 +618,19 @@ static int fixup_options(struct thread_data *td) ret |= 1; } + if (td_trimwrite(td) && o->num_range > 1) { + log_err("fio: trimwrite cannot be used with multiple" + " ranges.\n"); + ret |= 1; + } + + if (td_trim(td) && o->num_range > 1 && + !td_ioengine_flagged(td, FIO_MULTI_RANGE_TRIM)) { + log_err("fio: can't use multiple ranges with IO engine %s\n", + td->io_ops->name); + ret |= 1; + } + #ifndef CONFIG_PSHARED if (!o->use_thread) { log_info("fio: this platform does not support process shared" @@ -916,12 +929,6 @@ static int fixup_options(struct thread_data *td) ret |= 1; } - /* - * O_ATOMIC implies O_DIRECT - */ - if (o->oatomic) - o->odirect = 1; - /* * If randseed is set, that overrides randrepeat */ @@ -957,13 +964,16 @@ static int fixup_options(struct thread_data *td) if (o->disable_slat) o->slat_percentiles = 0; - /* - * Fix these up to be nsec internally - */ - for_each_rw_ddir(ddir) - o->max_latency[ddir] *= 1000ULL; + /* Do this only for the parent job */ + if (!td->subjob_number) { + /* + * Fix these up to be nsec internally + */ + for_each_rw_ddir(ddir) + o->max_latency[ddir] *= 1000ULL; - o->latency_target *= 1000ULL; + o->latency_target *= 1000ULL; + } /* * Dedupe working set verifications @@ -987,6 +997,33 @@ static int fixup_options(struct thread_data *td) } } + for_each_td(td2) { + if (td->o.ss_check_interval != td2->o.ss_check_interval) { + log_err("fio: conflicting ss_check_interval: %llu and %llu, must be globally equal\n", + td->o.ss_check_interval, td2->o.ss_check_interval); + ret |= 1; + } + } end_for_each(); + if (td->o.ss_dur && td->o.ss_check_interval / 1000L < 1000) { + log_err("fio: ss_check_interval must be at least 1s\n"); + ret |= 1; + + } + if (td->o.ss_dur && (td->o.ss_dur % td->o.ss_check_interval != 0 || td->o.ss_dur <= td->o.ss_check_interval)) { + log_err("fio: ss_duration %lluus must be multiple of ss_check_interval %lluus\n", + td->o.ss_dur, td->o.ss_check_interval); + ret |= 1; + } + + if (td->o.fdp) { + if (fio_option_is_set(&td->o, dp_type) && + (td->o.dp_type == FIO_DP_STREAMS || td->o.dp_type == FIO_DP_NONE)) { + log_err("fio: fdp=1 is not compatible with dataplacement={streams, none}\n"); + ret |= 1; + } else { + td->o.dp_type = FIO_DP_FDP; + } + } return ret; } @@ -1007,8 +1044,12 @@ static void init_rand_file_service(struct thread_data *td) } } -void td_fill_verify_state_seed(struct thread_data *td) +void td_fill_rand_seeds(struct thread_data *td) { + 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; bool use64; if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64) @@ -1016,17 +1057,6 @@ void td_fill_verify_state_seed(struct thread_data *td) else use64 = false; - init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF], - use64); -} - -static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64) -{ - 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; - /* * trimwrite is special in that we need to generate the same * offsets to get the "write after trim" effect. If we are @@ -1043,7 +1073,8 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64) init_rand_seed(&td->bsrange_state[DDIR_WRITE], write_seed, use64); init_rand_seed(&td->bsrange_state[DDIR_TRIM], trim_seed, use64); - td_fill_verify_state_seed(td); + init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF], + use64); init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF], false); if (td->o.file_service_type == FIO_FSERVICE_RANDOM) @@ -1062,12 +1093,6 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64) init_rand_seed(&td->prio_state, td->rand_seeds[FIO_RAND_PRIO_CMDS], false); init_rand_seed(&td->dedupe_working_set_index_state, td->rand_seeds[FIO_RAND_DEDUPE_WORKING_SET_IX], use64); - if (!td_random(td)) - return; - - if (td->o.rand_repeatable) - td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number; - init_rand_seed(&td->random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF], use64); for (i = 0; i < DDIR_RWDIR_CNT; i++) { @@ -1075,29 +1100,41 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64) init_rand_seed(s, td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], false); } + + init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF], use64); + frand_copy(&td->buf_state_prev, &td->buf_state); + + init_rand_seed(&td->fdp_state, td->rand_seeds[FIO_RAND_FDP_OFF], use64); } -void td_fill_rand_seeds(struct thread_data *td) +static int setup_random_seeds(struct thread_data *td) { - bool use64; - - if (td->o.allrand_repeatable) { - unsigned int i; + uint64_t seed; + unsigned int i; - for (i = 0; i < FIO_RAND_NR_OFFS; i++) - td->rand_seeds[i] = FIO_RANDSEED * td->thread_number - + i; + 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)); + dprint(FD_RANDOM, "using system RNG for random seeds\n"); + if (ret) + return ret; + } else { + seed = td->o.rand_seed; + for (i = 0; i < 4; i++) + seed *= 0x9e370001UL; + + for (i = 0; i < FIO_RAND_NR_OFFS; i++) { + td->rand_seeds[i] = seed * td->thread_number + i; + seed *= 0x9e370001UL; + } } - if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64) - use64 = true; - else - use64 = false; + td_fill_rand_seeds(td); - td_fill_rand_seeds_internal(td, use64); + dprint(FD_RANDOM, "FIO_RAND_NR_OFFS=%d\n", FIO_RAND_NR_OFFS); + for (int i = 0; i < FIO_RAND_NR_OFFS; i++) + dprint(FD_RANDOM, "rand_seeds[%d]=%" PRIu64 "\n", i, td->rand_seeds[i]); - init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF], use64); - frand_copy(&td->buf_state_prev, &td->buf_state); + return 0; } /* @@ -1233,31 +1270,6 @@ static void init_flags(struct thread_data *td) } } -static int setup_random_seeds(struct thread_data *td) -{ - uint64_t seed; - unsigned int i; - - 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++) - seed *= 0x9e370001UL; - - for (i = 0; i < FIO_RAND_NR_OFFS; i++) { - td->rand_seeds[i] = seed * td->thread_number + i; - seed *= 0x9e370001UL; - } - - td_fill_rand_seeds(td); - return 0; -} - enum { FPRE_NONE = 0, FPRE_JOBNAME, @@ -1411,15 +1423,14 @@ static void gen_log_name(char *name, size_t size, const char *logtype, static int check_waitees(char *waitee) { - struct thread_data *td; - int i, ret = 0; + int ret = 0; - for_each_td(td, i) { + for_each_td(td) { if (td->subjob_number) continue; ret += !strcmp(td->o.name, waitee); - } + } end_for_each(); return ret; } @@ -1454,10 +1465,7 @@ static bool wait_for_ok(const char *jobname, struct thread_options *o) static int verify_per_group_options(struct thread_data *td, const char *jobname) { - struct thread_data *td2; - int i; - - for_each_td(td2, i) { + for_each_td(td2) { if (td->groupid != td2->groupid) continue; @@ -1467,7 +1475,7 @@ static int verify_per_group_options(struct thread_data *td, const char *jobname) jobname); return 1; } - } + } end_for_each(); return 0; } @@ -1541,7 +1549,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, if (fixup_options(td)) goto err; - if (init_dedupe_working_set_seeds(td)) + if (!td->o.dedupe_global && init_dedupe_working_set_seeds(td, 0)) goto err; /* @@ -1576,7 +1584,14 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, td->ts.sig_figs = o->sig_figs; init_thread_stat_min_vals(&td->ts); - td->ddir_seq_nr = o->ddir_seq_nr; + + /* + * td->>ddir_seq_nr needs to be initialized to 1, NOT o->ddir_seq_nr, + * so that get_next_offset gets a new random offset the first time it + * is called, instead of keeping an initial offset of 0 for the first + * nr-1 calls + */ + td->ddir_seq_nr = 1; if ((o->stonewall || o->new_group) && prev_group_jobs) { prev_group_jobs = 0; @@ -1957,8 +1972,7 @@ static int __parse_jobs_ini(struct thread_data *td, * it's really 256 + small bit, 280 should suffice */ if (!nested) { - name = malloc(280); - memset(name, 0, 280); + name = calloc(1, 280); } opts = NULL; @@ -2178,6 +2192,10 @@ static int __parse_jobs_ini(struct thread_data *td, i++; } + free(job_sections); + job_sections = NULL; + nr_job_sections = 0; + free(opts); out: free(string); @@ -2258,7 +2276,7 @@ static void usage(const char *name) printf(" --minimal\t\tMinimal (terse) output\n"); printf(" --output-format=type\tOutput format (terse,json,json+,normal)\n"); printf(" --terse-version=type\tSet terse version output format" - " (default 3, or 2 or 4)\n"); + " (default 3, or 2 or 4 or 5)\n"); 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"); @@ -2799,6 +2817,15 @@ int parse_cmd_line(int argc, char *argv[], int client_type) break; ret = fio_cmd_ioengine_option_parse(td, opt, val); + + if (ret) { + if (td) { + put_job(td); + td = NULL; + } + do_exit++; + exit_val = 1; + } break; } case 'w': @@ -2979,7 +3006,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; + fio_fallthrough; default: do_exit++; exit_val = 1;