#define FIO_RANDSEED (0xb1899bedUL)
static char **ini_file;
-static int max_jobs = FIO_MAX_JOBS;
static bool dump_cmdline;
static bool parse_only;
static bool merge_blktrace_only;
.has_arg = optional_argument,
.val = 'S',
},
+#ifdef WIN32
+ {
+ .name = (char *) "server-internal",
+ .has_arg = required_argument,
+ .val = 'N',
+ },
+#endif
{ .name = (char *) "daemonize",
.has_arg = required_argument,
.val = 'D',
static void free_shm(void)
{
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if (nr_segments) {
flow_exit();
fio_debug_jobp = NULL;
fio_filelock_exit();
file_hash_exit();
scleanup();
+#endif
}
static int add_thread_segment(void)
size_t size = JOBS_PER_SEG * sizeof(struct thread_data);
int i;
- if (nr_segments + 1 >= REAL_MAX_SEG)
+ if (nr_segments + 1 >= REAL_MAX_SEG) {
+ log_err("error: maximum number of jobs reached.\n");
return -1;
+ }
size += 2 * sizeof(unsigned int);
}
}
-static void fio_dump_options_free(struct thread_data *td)
-{
- while (!flist_empty(&td->opt_list)) {
- struct print_option *p;
-
- p = flist_first_entry(&td->opt_list, struct print_option, list);
- flist_del_init(&p->list);
- free(p->name);
- free(p->value);
- free(p);
- }
-}
-
static void copy_opt_list(struct thread_data *dst, struct thread_data *src)
{
struct flist_head *entry;
log_err("error: failed to setup shm segment\n");
return NULL;
}
- if (thread_number >= max_jobs) {
- log_err("error: maximum number of jobs (%d) reached.\n",
- max_jobs);
- return NULL;
- }
seg = &segments[cur_segment];
td = &seg->threads[seg->nr_threads++];
ret |= 1;
}
+ if (o->zone_mode == ZONE_MODE_ZBD && !o->create_serialize) {
+ log_err("fio: --zonemode=zbd and --create_serialize=0 are not compatible.\n");
+ ret |= 1;
+ }
+
if (o->zone_mode == ZONE_MODE_STRIDED && !o->zone_size) {
log_err("fio: --zonesize must be specified when using --zonemode=strided.\n");
ret |= 1;
/*
* Fix these up to be nsec internally
*/
- o->max_latency *= 1000ULL;
+ for_each_rw_ddir(ddir)
+ o->max_latency[ddir] *= 1000ULL;
+
o->latency_target *= 1000ULL;
+ /*
+ * Dedupe working set verifications
+ */
+ if (o->dedupe_percentage && o->dedupe_mode == DEDUPE_MODE_WORKING_SET) {
+ if (!fio_option_is_set(o, size)) {
+ log_err("fio: pregenerated dedupe working set "
+ "requires size to be set\n");
+ ret |= 1;
+ } else if (o->nr_files != 1) {
+ log_err("fio: dedupe working set mode supported with "
+ "single file per job, but %d files "
+ "provided\n", o->nr_files);
+ ret |= 1;
+ } else if (o->dedupe_working_set_percentage + o->dedupe_percentage > 100) {
+ log_err("fio: impossible to reach expected dedupe percentage %u "
+ "since %u percentage of size is reserved to dedupe working set "
+ "(those are unique pages)\n",
+ o->dedupe_percentage, o->dedupe_working_set_percentage);
+ ret |= 1;
+ }
+ }
+
return ret;
}
const unsigned int seed = td->rand_seeds[FIO_RAND_FILE_OFF];
if (td->o.file_service_type == FIO_FSERVICE_ZIPF) {
- zipf_init(&td->next_file_zipf, nranges, td->zipf_theta, seed);
+ zipf_init(&td->next_file_zipf, nranges, td->zipf_theta, td->random_center, seed);
zipf_disable_hash(&td->next_file_zipf);
} else if (td->o.file_service_type == FIO_FSERVICE_PARETO) {
- pareto_init(&td->next_file_zipf, nranges, td->pareto_h, seed);
+ pareto_init(&td->next_file_zipf, nranges, td->pareto_h, td->random_center, seed);
zipf_disable_hash(&td->next_file_zipf);
} else if (td->o.file_service_type == FIO_FSERVICE_GAUSS) {
- gauss_init(&td->next_file_gauss, nranges, td->gauss_dev, seed);
+ gauss_init(&td->next_file_gauss, nranges, td->gauss_dev, td->random_center, seed);
gauss_disable_hash(&td->next_file_gauss);
}
}
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);
+ init_rand_seed(&td->dedupe_working_set_index_state, td->rand_seeds[FIO_RAND_DEDUPE_WORKING_SET_IX], use64);
if (!td_random(td))
return;
* for this name and see if they match. If they do, then
* the engine is unchanged.
*/
- dlhandle = td->io_ops_dlhandle;
+ 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);
+ if (ops == td->io_ops && dlhandle == td->io_ops->dlhandle)
return 0;
- }
- if (dlhandle && dlhandle != td->io_ops_dlhandle)
+ if (dlhandle && dlhandle != td->io_ops->dlhandle)
dlclose(dlhandle);
/* Unload the old engine. */
FPRE_NONE = 0,
FPRE_JOBNAME,
FPRE_JOBNUM,
- FPRE_FILENUM
+ FPRE_FILENUM,
+ FPRE_CLIENTUID
};
static struct fpre_keyword {
{ .keyword = "$jobname", .key = FPRE_JOBNAME, },
{ .keyword = "$jobnum", .key = FPRE_JOBNUM, },
{ .keyword = "$filenum", .key = FPRE_FILENUM, },
+ { .keyword = "$clientuid", .key = FPRE_CLIENTUID, },
{ .keyword = NULL, },
};
}
break;
}
+ case FPRE_CLIENTUID: {
+ int ret;
+ ret = snprintf(dst, dst_left, "%s", client_sockaddr_str);
+ if (ret < 0)
+ break;
+ else if (ret > dst_left) {
+ log_err("fio: truncated filename\n");
+ dst += dst_left;
+ dst_left = 0;
+ } else {
+ dst += ret;
+ dst_left -= ret;
+ }
+ break;
+ }
default:
assert(0);
break;
return true;
}
+static int verify_per_group_options(struct thread_data *td, const char *jobname)
+{
+ struct thread_data *td2;
+ int i;
+
+ for_each_td(td2, i) {
+ if (td->groupid != td2->groupid)
+ continue;
+
+ if (td->o.stats &&
+ td->o.lat_percentiles != td2->o.lat_percentiles) {
+ log_err("fio: lat_percentiles in job: %s differs from group\n",
+ jobname);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/*
* Treat an empty log file name the same as a one not given
*/
if (fixup_options(td))
goto err;
+ if (init_dedupe_working_set_seeds(td))
+ goto err;
+
/*
* Belongs to fixup_options, but o->name is not necessarily set as yet
*/
memcpy(td->ts.percentile_list, o->percentile_list, sizeof(o->percentile_list));
td->ts.sig_figs = o->sig_figs;
- for (i = 0; i < DDIR_RWDIR_CNT; i++) {
- td->ts.clat_stat[i].min_val = ULONG_MAX;
- 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->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;
+ init_thread_stat_min_vals(&td->ts);
td->ddir_seq_nr = o->ddir_seq_nr;
if ((o->stonewall || o->new_group) && prev_group_jobs) {
td->groupid = groupid;
prev_group_jobs++;
+ if (td->o.group_reporting && prev_group_jobs > 1 &&
+ verify_per_group_options(td, jobname))
+ goto err;
+
if (setup_rate(td))
goto err;
.hist_coarseness = o->log_hist_coarseness,
.log_type = IO_LOG_TYPE_LAT,
.log_offset = o->log_offset,
+ .log_prio = o->log_prio,
.log_gz = o->log_gz,
.log_gz_store = o->log_gz_store,
};
else
suf = "log";
- gen_log_name(logname, sizeof(logname), "lat", pre,
- td->thread_number, suf, o->per_job_logs);
- setup_log(&td->lat_log, &p, logname);
+ if (!o->disable_lat) {
+ gen_log_name(logname, sizeof(logname), "lat", pre,
+ td->thread_number, suf, o->per_job_logs);
+ setup_log(&td->lat_log, &p, logname);
+ }
- gen_log_name(logname, sizeof(logname), "slat", pre,
- td->thread_number, suf, o->per_job_logs);
- setup_log(&td->slat_log, &p, logname);
+ if (!o->disable_slat) {
+ gen_log_name(logname, sizeof(logname), "slat", pre,
+ td->thread_number, suf, o->per_job_logs);
+ setup_log(&td->slat_log, &p, logname);
+ }
- gen_log_name(logname, sizeof(logname), "clat", pre,
- td->thread_number, suf, o->per_job_logs);
- setup_log(&td->clat_log, &p, logname);
+ if (!o->disable_clat) {
+ gen_log_name(logname, sizeof(logname), "clat", pre,
+ td->thread_number, suf, o->per_job_logs);
+ setup_log(&td->clat_log, &p, logname);
+ }
}
.hist_coarseness = o->log_hist_coarseness,
.log_type = IO_LOG_TYPE_HIST,
.log_offset = o->log_offset,
+ .log_prio = o->log_prio,
.log_gz = o->log_gz,
.log_gz_store = o->log_gz_store,
};
.hist_coarseness = o->log_hist_coarseness,
.log_type = IO_LOG_TYPE_BW,
.log_offset = o->log_offset,
+ .log_prio = o->log_prio,
.log_gz = o->log_gz,
.log_gz_store = o->log_gz_store,
};
.hist_coarseness = o->log_hist_coarseness,
.log_type = IO_LOG_TYPE_IOPS,
.log_offset = o->log_offset,
+ .log_prio = o->log_prio,
.log_gz = o->log_gz,
.log_gz_store = o->log_gz_store,
};
warnings_fatal = 1;
break;
case 'j':
- max_jobs = atoi(optarg);
- if (!max_jobs || max_jobs > REAL_MAX_JOBS) {
- log_err("fio: invalid max jobs: %d\n", max_jobs);
- do_exit++;
- exit_val = 1;
- }
+ /* we don't track/need this anymore, ignore it */
break;
case 'S':
did_arg = true;
exit_val = 1;
#endif
break;
+#ifdef WIN32
+ case 'N':
+ did_arg = true;
+ fio_server_internal_set(optarg);
+ break;
+#endif
case 'D':
if (pid_file)
free(pid_file);