#include "steadystate.h"
#include "blktrace.h"
+#include "oslib/asprintf.h"
#include "oslib/getopt.h"
#include "oslib/strcasestr.h"
{
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;
}
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] ||
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) {
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()"
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;
}
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;
/*
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;
*/
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);
}
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) {
/*
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)
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++) {
if (post_start)
strncpy(dst, buf + post_start, dst_left);
- strncpy(buf, copy, buf_size - 1);
+ snprintf(buf, buf_size, "%s", copy);
} while (1);
}
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;
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;
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;
}
int nested, char *name, char ***popts, int *aopts, int *nopts)
{
bool global = false;
+ bool stdin_occupied = false;
char *string;
FILE *f;
char *p;
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) {
*/
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,
- len - (ts - file) - 1);
- full_fn[len - 1] = 0;
filename = full_fn;
}
}
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);
case 'i':
did_arg = true;
if (!cur_client) {
- fio_show_ioengine_help(optarg);
+ exit_val = fio_show_ioengine_help(optarg);
do_exit++;
}
break;
log_err("%s: unrecognized option '%s'\n", argv[0],
argv[optind - 1]);
show_closest_option(argv[optind - 1]);
- /* fall through */
+ fallthrough;
default:
do_exit++;
exit_val = 1;