X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=init.c;h=3710e3d404acf84599076098cbe6569282b448a8;hb=b6b64bfec2dd4ce7db64c57ecf771bb7b2f105f6;hp=392dda2ce9f1ac11d4444cb5d8d56c1f0e243aaf;hpb=1e2c3404a2a223a3c5358c207f4436564f2aae9b;p=fio.git diff --git a/init.c b/init.c index 392dda2c..3710e3d4 100644 --- a/init.c +++ b/init.c @@ -30,7 +30,9 @@ #include "idletime.h" #include "filelock.h" #include "steadystate.h" +#include "blktrace.h" +#include "oslib/asprintf.h" #include "oslib/getopt.h" #include "oslib/strcasestr.h" @@ -44,15 +46,16 @@ const char fio_version_string[] = FIO_VERSION; static char **ini_file; static int max_jobs = FIO_MAX_JOBS; -static int dump_cmdline; -static int parse_only; +static bool dump_cmdline; +static bool parse_only; +static bool merge_blktrace_only; static struct thread_data def_thread; struct thread_data *threads = NULL; static char **job_sections; static int nr_job_sections; -int exitall_on_terminate = 0; +bool exitall_on_terminate = false; int output_format = FIO_OUTPUT_NORMAL; int eta_print = FIO_ETA_AUTO; unsigned int eta_interval_msec = 1000; @@ -62,13 +65,13 @@ FILE *f_err = NULL; char *exec_profile = NULL; int warnings_fatal = 0; int terse_version = 3; -int is_backend = 0; -int is_local_backend = 0; +bool is_backend = false; +bool is_local_backend = false; int nr_clients = 0; -int log_syslog = 0; +bool log_syslog = false; -int write_bw_log = 0; -int read_only = 0; +bool write_bw_log = false; +bool read_only = false; int status_interval = 0; char *trigger_file = NULL; @@ -286,6 +289,11 @@ static struct option l_opts[FIO_NR_OPTIONS] = { .has_arg = required_argument, .val = 'K', }, + { + .name = (char *) "merge-blktrace-only", + .has_arg = no_argument, + .val = 'A' | FIO_CLIENT_FLAG, + }, { .name = NULL, }, @@ -737,19 +745,12 @@ static int fixup_options(struct thread_data *td) /* * 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 + * when we are not in offload mode */ if (o->serialize_overlap && !(td->flags & TD_F_READ_IOLOG) && - (!(td_write(td) || td_trim(td)) || o->iodepth == 1)) + (!(td_write(td) || td_trim(td)) || o->iodepth == 1) && + o->io_submit_mode != IO_MODE_OFFLOAD) 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; @@ -852,11 +853,6 @@ static int fixup_options(struct thread_data *td) 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()" @@ -948,31 +944,18 @@ static int fixup_options(struct thread_data *td) 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; } @@ -1009,9 +992,9 @@ void td_fill_verify_state_seed(struct thread_data *td) 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; /* @@ -1046,6 +1029,7 @@ static void td_fill_rand_seeds_internal(struct thread_data *td, bool use64) 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; @@ -1115,6 +1099,9 @@ int ioengine_load(struct thread_data *td) */ 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); @@ -1129,10 +1116,8 @@ int ioengine_load(struct thread_data *td) } 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) { /* @@ -1171,6 +1156,11 @@ int ioengine_load(struct thread_data *td) 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) @@ -1217,7 +1207,7 @@ static void init_flags(struct thread_data *td) static int setup_random_seeds(struct thread_data *td) { - unsigned long seed; + uint64_t seed; unsigned int i; if (!td->o.rand_repeatable && !fio_option_is_set(&td->o, rand_seed)) { @@ -1273,8 +1263,7 @@ static char *make_filename(char *buf, size_t buf_size,struct thread_options *o, 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++) { @@ -1353,7 +1342,7 @@ static char *make_filename(char *buf, size_t buf_size,struct thread_options *o, if (post_start) strncpy(dst, buf + post_start, dst_left); - strncpy(buf, copy, buf_size - 1); + snprintf(buf, buf_size, "%s", copy); } while (1); } @@ -1418,6 +1407,17 @@ static bool wait_for_ok(const char *jobname, struct thread_options *o) return true; } +/* + * Treat an empty log file name the same as a one not given + */ +static const char *make_log_name(const char *logname, const char *jobname) +{ + if (logname && strcmp(logname, "")) + return logname; + + return jobname; +} + /* * Adds a job to the list of things todo. Sanitizes the various options * to make sure we don't have conflicts, and initializes various @@ -1427,7 +1427,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, int recursed, int client_type) { unsigned int i; - char fname[PATH_MAX]; + char fname[PATH_MAX + 1]; int numjobs, file_alloced; struct thread_options *o = &td->o; char logname[PATH_MAX + 32]; @@ -1502,6 +1502,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, 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; @@ -1512,6 +1513,8 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, 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; @@ -1542,9 +1545,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, .log_gz = o->log_gz, .log_gz_store = o->log_gz_store, }; - const char *pre = - (o->lat_log_file && strcmp(o->lat_log_file, "") != 0) ? - o->lat_log_file : o->name; + const char *pre = make_log_name(o->lat_log_file, o->name); const char *suf; if (p.log_gz_store) @@ -1577,9 +1578,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, .log_gz = o->log_gz, .log_gz_store = o->log_gz_store, }; - const char *pre = - (o->hist_log_file && strcmp(o->hist_log_file, "") != 0) ? - o->hist_log_file : o->name; + const char *pre = make_log_name(o->hist_log_file, o->name); const char *suf; #ifndef CONFIG_ZLIB @@ -1610,9 +1609,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, .log_gz = o->log_gz, .log_gz_store = o->log_gz_store, }; - const char *pre = - (o->bw_log_file && strcmp(o->bw_log_file, "") != 0) ? - o->bw_log_file : o->name; + const char *pre = make_log_name(o->bw_log_file, o->name); const char *suf; if (fio_option_is_set(o, bw_avg_time)) @@ -1643,9 +1640,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, .log_gz = o->log_gz, .log_gz_store = o->log_gz_store, }; - const char *pre = - (o->iops_log_file && strcmp(o->iops_log_file, "") != 0) ? - o->iops_log_file : o->name; + const char *pre = make_log_name(o->iops_log_file, o->name); const char *suf; if (fio_option_is_set(o, iops_avg_time)) @@ -1678,6 +1673,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, char *c1, *c2, *c3, *c4; char *c5 = NULL, *c6 = NULL; int i2p = is_power_of_2(o->kb_base); + struct buf_output out; c1 = num2str(o->min_bs[DDIR_READ], o->sig_figs, 1, i2p, N2S_BYTE); c2 = num2str(o->max_bs[DDIR_READ], o->sig_figs, 1, i2p, N2S_BYTE); @@ -1689,19 +1685,22 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, c6 = num2str(o->max_bs[DDIR_TRIM], o->sig_figs, 1, i2p, N2S_BYTE); } - log_info("%s: (g=%d): rw=%s, ", td->o.name, + buf_output_init(&out); + __log_buf(&out, "%s: (g=%d): rw=%s, ", td->o.name, td->groupid, ddir_str(o->td_ddir)); if (o->bs_is_seq_rand) - log_info("bs=(R) %s-%s, (W) %s-%s, bs_is_seq_rand, ", + __log_buf(&out, "bs=(R) %s-%s, (W) %s-%s, bs_is_seq_rand, ", c1, c2, c3, c4); else - log_info("bs=(R) %s-%s, (W) %s-%s, (T) %s-%s, ", + __log_buf(&out, "bs=(R) %s-%s, (W) %s-%s, (T) %s-%s, ", c1, c2, c3, c4, c5, c6); - log_info("ioengine=%s, iodepth=%u\n", + __log_buf(&out, "ioengine=%s, iodepth=%u\n", td->io_ops->name, o->iodepth); + log_info_buf(out.buf, out.buflen); + buf_output_free(&out); free(c1); free(c2); @@ -1717,6 +1716,14 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, if (td_steadystate_init(td)) goto err; + if (o->merge_blktrace_file && !merge_blktrace_iologs(td)) + goto err; + + if (merge_blktrace_only) { + put_job(td); + return 0; + } + /* * recurse add identical jobs, clear numjobs and stonewall options * as they don't apply to sub-jobs @@ -1872,7 +1879,7 @@ static int __parse_jobs_ini(struct thread_data *td, } } - string = malloc(4096); + string = malloc(OPT_LEN_MAX); /* * it's really 256 + small bit, 280 should suffice @@ -1905,7 +1912,7 @@ static int __parse_jobs_ini(struct thread_data *td, if (is_buf) p = strsep(&file, "\n"); else - p = fgets(string, 4096, f); + p = fgets(string, OPT_LEN_MAX, f); if (!p) break; } @@ -1974,7 +1981,7 @@ static int __parse_jobs_ini(struct thread_data *td, if (is_buf) p = strsep(&file, "\n"); else - p = fgets(string, 4096, f); + p = fgets(string, OPT_LEN_MAX, f); if (!p) break; dprint(FD_PARSE, "%s", p); @@ -2014,19 +2021,12 @@ static int __parse_jobs_ini(struct thread_data *td, */ 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, strlen(filename)); - full_fn[len - 1] = 0; filename = full_fn; } @@ -2166,6 +2166,7 @@ static void usage(const char *name) 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(" --merge-blktrace-only\tMerge blktraces only, don't start any IO\n"); printf(" --output\t\tWrite output to file\n"); printf(" --bandwidth-log\tGenerate aggregate bandwidth logs\n"); printf(" --minimal\t\tMinimal (terse) output\n"); @@ -2464,7 +2465,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type) char *ostr = cmd_optstr; char *pid_file = NULL; void *cur_client = NULL; - int backend = 0; + bool backend = false; /* * Reset optind handling, since we may call this multiple times @@ -2490,7 +2491,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type) exit_val = 1; break; case 'b': - write_bw_log = 1; + write_bw_log = true; break; case 'o': { FILE *tmp; @@ -2545,7 +2546,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type) break; case 's': did_arg = true; - dump_cmdline = 1; + dump_cmdline = true; break; case 'r': read_only = 1; @@ -2611,7 +2612,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type) break; case 'P': did_arg = true; - parse_only = 1; + parse_only = true; break; case 'x': { size_t new_size; @@ -2736,8 +2737,8 @@ int parse_cmd_line(int argc, char *argv[], int client_type) } if (optarg) fio_server_set_arg(optarg); - is_backend = 1; - backend = 1; + is_backend = true; + backend = true; #else log_err("fio: client/server requires SHM support\n"); do_exit++; @@ -2882,10 +2883,16 @@ int parse_cmd_line(int argc, char *argv[], int client_type) } trigger_timeout /= 1000000; break; + + case 'A': + did_arg = true; + merge_blktrace_only = true; + break; case '?': log_err("%s: unrecognized option '%s'\n", argv[0], argv[optind - 1]); show_closest_option(argv[optind - 1]); + /* fall through */ default: do_exit++; exit_val = 1;