static unsigned long long get_rand_start_delay(struct thread_data *td)
{
unsigned long long delayrange;
+ uint64_t frand_max;
unsigned long r;
delayrange = td->o.start_delay_high - td->o.start_delay;
+ frand_max = rand_max(&td->delay_state);
r = __rand(&td->delay_state);
- delayrange = (unsigned long long) ((double) delayrange * (r / (FRAND_MAX + 1.0)));
+ delayrange = (unsigned long long) ((double) delayrange * (r / (frand_max + 1.0)));
delayrange += td->o.start_delay;
return delayrange;
if (o->norandommap && o->verify != VERIFY_NONE
&& !fixed_block_size(o)) {
log_err("fio: norandommap given for variable block sizes, "
- "verify disabled\n");
- o->verify = VERIFY_NONE;
+ "verify limited\n");
ret = warnings_fatal;
}
if (o->bs_unaligned && (o->odirect || td->io_ops->flags & FIO_RAWIO))
/*
* If randseed is set, that overrides randrepeat
*/
- if (td->o.rand_seed)
+ if (fio_option_is_set(&td->o, rand_seed))
td->o.rand_repeatable = 0;
if ((td->io_ops->flags & FIO_NOEXTEND) && td->o.file_append) {
fio_gtod_offload = 1;
}
+ td->loops = o->loops;
+ if (!td->loops)
+ td->loops = 1;
+
+ if (td->o.block_error_hist && td->o.nr_files != 1) {
+ log_err("fio: block error histogram only available with "
+ "with a single file per job, but %d files "
+ "provided\n", td->o.nr_files);
+ ret = 1;
+ }
+
return ret;
}
return 1;
}
-static void td_fill_rand_seeds_internal(struct thread_data *td)
+static void td_fill_rand_seeds_internal(struct thread_data *td, int use64)
{
- init_rand_seed(&td->bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF]);
- init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF]);
- init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF]);
+ init_rand_seed(&td->bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF], use64);
+ 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], use64);
if (td->o.file_service_type == FIO_FSERVICE_RANDOM)
- init_rand_seed(&td->next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF]);
+ init_rand_seed(&td->next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF], use64);
- init_rand_seed(&td->file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF]);
- init_rand_seed(&td->trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF]);
- init_rand_seed(&td->delay_state, td->rand_seeds[FIO_RAND_START_DELAY]);
+ 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);
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]);
- init_rand_seed(&td->seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF]);
- init_rand_seed(&td->seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF]);
- init_rand_seed(&td->seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF]);
+ init_rand_seed(&td->random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF], use64);
+ init_rand_seed(&td->seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], use64);
+ init_rand_seed(&td->seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF], use64);
+ init_rand_seed(&td->seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF], use64);
}
void td_fill_rand_seeds(struct thread_data *td)
{
+ int use64;
+
if (td->o.allrand_repeatable) {
unsigned int i;
+ i;
}
- td_fill_rand_seeds_internal(td);
+ if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64)
+ use64 = 1;
+ else
+ use64 = 0;
+
+ td_fill_rand_seeds_internal(td, use64);
- init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF]);
+ 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->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF]);
+ init_rand_seed(&td->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF], use64);
}
/*
td->flags |= TD_F_SCRAMBLE_BUFFERS;
if (o->verify != VERIFY_NONE)
td->flags |= TD_F_VER_NONE;
+
+ if (o->verify_async || o->io_submit_mode == IO_MODE_OFFLOAD)
+ td->flags |= TD_F_NEED_LOCK;
}
static int setup_random_seeds(struct thread_data *td)
unsigned long seed;
unsigned int i;
- if (!td->o.rand_repeatable && !td->o.rand_seed)
+ 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_seed)
- seed = 0x89;
- else
- seed = td->o.rand_seed;
-
+ seed = td->o.rand_seed;
for (i = 0; i < 4; i++)
seed *= 0x9e370001UL;
return dump_cmdline || parse_only;
}
+static void gen_log_name(char *name, size_t size, const char *logtype,
+ const char *logname, unsigned int num,
+ const char *suf, int per_job)
+{
+ if (per_job)
+ snprintf(name, size, "%s_%s.%d.%s", logname, logtype, num, suf);
+ else
+ snprintf(name, size, "%s_%s.%s", logname, logtype, suf);
+}
+
/*
* Adds a job to the list of things todo. Sanitizes the various options
* to make sure we don't have conflicts, and initializes various
else
suf = "log";
- snprintf(logname, sizeof(logname), "%s_lat.%d.%s",
- o->lat_log_file, td->thread_number, suf);
+ gen_log_name(logname, sizeof(logname), "lat", o->lat_log_file,
+ td->thread_number, suf, o->per_job_logs);
setup_log(&td->lat_log, &p, logname);
- snprintf(logname, sizeof(logname), "%s_slat.%d.%s",
- o->lat_log_file, td->thread_number, suf);
+
+ gen_log_name(logname, sizeof(logname), "slat", o->lat_log_file,
+ td->thread_number, suf, o->per_job_logs);
setup_log(&td->slat_log, &p, logname);
- snprintf(logname, sizeof(logname), "%s_clat.%d.%s",
- o->lat_log_file, td->thread_number, suf);
+
+ gen_log_name(logname, sizeof(logname), "clat", o->lat_log_file,
+ td->thread_number, suf, o->per_job_logs);
setup_log(&td->clat_log, &p, logname);
}
if (o->bw_log_file) {
else
suf = "log";
- snprintf(logname, sizeof(logname), "%s_bw.%d.%s",
- o->bw_log_file, td->thread_number, suf);
+ gen_log_name(logname, sizeof(logname), "bw", o->bw_log_file,
+ td->thread_number, suf, o->per_job_logs);
setup_log(&td->bw_log, &p, logname);
}
if (o->iops_log_file) {
else
suf = "log";
- snprintf(logname, sizeof(logname), "%s_iops.%d.%s",
- o->iops_log_file, td->thread_number, suf);
+ gen_log_name(logname, sizeof(logname), "iops", o->iops_log_file,
+ td->thread_number, suf, o->per_job_logs);
setup_log(&td->iops_log, &p, logname);
}
return 0;
}
+static void show_debug_categories(void)
+{
+ struct debug_level *dl = &debug_levels[0];
+ int curlen, first = 1;
+
+ curlen = 0;
+ while (dl->name) {
+ int has_next = (dl + 1)->name != NULL;
+
+ if (first || curlen + strlen(dl->name) >= 80) {
+ if (!first) {
+ printf("\n");
+ curlen = 0;
+ }
+ curlen += printf("\t\t\t%s", dl->name);
+ curlen += 3 * (8 - 1);
+ if (has_next)
+ curlen += printf(",");
+ } else {
+ curlen += printf("%s", dl->name);
+ if (has_next)
+ curlen += printf(",");
+ }
+ dl++;
+ first = 0;
+ }
+ printf("\n");
+}
+
static void usage(const char *name)
{
printf("%s\n", fio_version_string);
printf("%s [options] [job options] <job file(s)>\n", name);
- printf(" --debug=options\tEnable debug logging. May be one/more of:\n"
- "\t\t\tprocess,file,io,mem,blktrace,verify,random,parse,\n"
- "\t\t\tdiskutil,job,mutex,profile,time,net,rate,compress\n");
+ printf(" --debug=options\tEnable debug logging. May be one/more of:\n");
+ show_debug_categories();
printf(" --parse-only\t\tParse options only, don't start any IO\n");
printf(" --output\t\tWrite output to file\n");
printf(" --runtime\t\tRuntime in seconds\n");
td = NULL;
}
do_exit++;
+ exit_val = 1;
break;
}
fio_options_set_ioengine_opts(l_opts, td);
td = NULL;
}
do_exit++;
+ exit_val = 1;
}
if (!ret && !strcmp(opt, "ioengine")) {
put_job(td);
td = NULL;
do_exit++;
+ exit_val = 1;
break;
}
fio_options_set_ioengine_opts(l_opts, td);
exit_val = 1;
break;
}
+ /* if --client parameter contains a pathname */
+ if (0 == access(optarg, R_OK)) {
+ /* file contains a list of host addrs or names */
+ char hostaddr[PATH_MAX] = {0};
+ char formatstr[8];
+ FILE * hostf = fopen(optarg, "r");
+ if (!hostf) {
+ log_err("fio: could not open client list file %s for read\n", optarg);
+ do_exit++;
+ exit_val = 1;
+ break;
+ }
+ sprintf(formatstr, "%%%ds", PATH_MAX - 1);
+ /*
+ * read at most PATH_MAX-1 chars from each
+ * record in this file
+ */
+ while (fscanf(hostf, formatstr, hostaddr) == 1) {
+ /* expect EVERY host in file to be valid */
+ if (fio_client_add(&fio_client_ops, hostaddr, &cur_client)) {
+ log_err("fio: failed adding client %s from file %s\n", hostaddr, optarg);
+ do_exit++;
+ exit_val = 1;
+ break;
+ }
+ }
+ fclose(hostf);
+ break; /* no possibility of job file for "this client only" */
+ }
if (fio_client_add(&fio_client_ops, optarg, &cur_client)) {
log_err("fio: failed adding client %s\n", optarg);
do_exit++;