X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=init.c;h=8d382602f4539bd75a2d8bc493c0dd6d1176c1ac;hp=b9da71335a7fc34aece77d4678949c35a276cdd1;hb=1cce3c66140206967462f85646a50b0065da87e9;hpb=db37d89074ed204c9c2bd010e72f63dcf4725715 diff --git a/init.c b/init.c index b9da7133..8d382602 100644 --- a/init.c +++ b/init.c @@ -4,13 +4,17 @@ #include #include #include -#include #include #include #include #include #include -#include +#include +#ifdef CONFIG_VALGRIND_DEV +#include +#else +#define DRD_IGNORE_VAR(x) do { } while (0) +#endif #include "fio.h" #ifndef FIO_NO_HAVE_SHM_H @@ -78,6 +82,7 @@ static int prev_group_jobs; unsigned long fio_debug = 0; unsigned int fio_debug_jobno = -1; unsigned int *fio_debug_jobp = NULL; +unsigned int *fio_warned = NULL; static char cmd_optstr[256]; static bool did_arg; @@ -308,6 +313,7 @@ static void free_shm(void) if (threads) { flow_exit(); fio_debug_jobp = NULL; + fio_warned = NULL; free_threads_shm(); } @@ -330,6 +336,8 @@ static void free_shm(void) */ static int setup_thread_area(void) { + int i; + if (threads) return 0; @@ -340,7 +348,7 @@ static int setup_thread_area(void) do { size_t size = max_jobs * sizeof(struct thread_data); - size += sizeof(unsigned int); + size += 2 * sizeof(unsigned int); #ifndef CONFIG_NO_SHM shm_id = shmget(0, size, IPC_CREAT | 0600); @@ -373,8 +381,12 @@ static int setup_thread_area(void) #endif memset(threads, 0, max_jobs * sizeof(struct thread_data)); + for (i = 0; i < max_jobs; i++) + DRD_IGNORE_VAR(threads[i]); fio_debug_jobp = (unsigned int *)(threads + max_jobs); *fio_debug_jobp = -1; + fio_warned = fio_debug_jobp + 1; + *fio_warned = 0; flow_init(); @@ -562,23 +574,6 @@ static int fixed_block_size(struct thread_options *o) o->min_bs[DDIR_READ] == o->min_bs[DDIR_TRIM]; } - -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 += td->o.start_delay; - return delayrange; -} - /* * <3 Johannes */ @@ -605,7 +600,7 @@ static int fixup_options(struct thread_data *td) " mutexes, forcing use of threads. Use the 'thread'" " option to get rid of this warning.\n"); o->use_thread = 1; - ret = warnings_fatal; + ret |= warnings_fatal; } #endif @@ -613,7 +608,7 @@ static int fixup_options(struct thread_data *td) log_err("fio: read iolog overrides write_iolog\n"); free(o->write_iolog_file); o->write_iolog_file = NULL; - ret = warnings_fatal; + ret |= warnings_fatal; } /* @@ -667,20 +662,25 @@ static int fixup_options(struct thread_data *td) !o->norandommap) { log_err("fio: Any use of blockalign= turns off randommap\n"); o->norandommap = 1; - ret = warnings_fatal; + ret |= warnings_fatal; } if (!o->file_size_high) o->file_size_high = o->file_size_low; - if (o->start_delay_high) - o->start_delay = get_rand_start_delay(td); + if (o->start_delay_high) { + if (!o->start_delay_orig) + o->start_delay_orig = o->start_delay; + o->start_delay = rand_between(&td->delay_state, + o->start_delay_orig, + o->start_delay_high); + } if (o->norandommap && o->verify != VERIFY_NONE && !fixed_block_size(o)) { log_err("fio: norandommap given for variable block sizes, " "verify limited\n"); - ret = warnings_fatal; + ret |= warnings_fatal; } if (o->bs_unaligned && (o->odirect || td_ioengine_flagged(td, FIO_RAWIO))) log_err("fio: bs_unaligned may not work with raw io\n"); @@ -724,7 +724,7 @@ static int fixup_options(struct thread_data *td) 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; + ret |= warnings_fatal; } if (o->nr_files > td->files_index) @@ -738,7 +738,7 @@ static int fixup_options(struct thread_data *td) ((o->ratemin[DDIR_READ] + o->ratemin[DDIR_WRITE] + o->ratemin[DDIR_TRIM]) && (o->rate_iops_min[DDIR_READ] + o->rate_iops_min[DDIR_WRITE] + o->rate_iops_min[DDIR_TRIM]))) { log_err("fio: rate and rate_iops are mutually exclusive\n"); - ret = 1; + 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])) || @@ -747,13 +747,13 @@ static int fixup_options(struct thread_data *td) (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; + ret |= 1; } if (!o->timeout && o->time_based) { log_err("fio: time_based requires a runtime/timeout setting\n"); o->time_based = 0; - ret = warnings_fatal; + ret |= warnings_fatal; } if (o->fill_device && !o->size) @@ -769,7 +769,7 @@ static int fixup_options(struct thread_data *td) log_info("fio: multiple writers may overwrite blocks " "that belong to other jobs. This can cause " "verification failures.\n"); - ret = warnings_fatal; + ret |= warnings_fatal; } /* @@ -781,7 +781,7 @@ static int fixup_options(struct thread_data *td) log_info("fio: verification read phase will never " "start because write phase uses all of " "runtime\n"); - ret = warnings_fatal; + ret |= warnings_fatal; } if (!fio_option_is_set(o, refill_buffers)) @@ -801,11 +801,12 @@ static int fixup_options(struct thread_data *td) o->verify_interval = o->min_bs[DDIR_READ]; /* - * Verify interval must be a factor or both min and max + * Verify interval must be a factor of both min and max * write size */ - if (o->verify_interval % o->min_bs[DDIR_WRITE] || - o->verify_interval % o->max_bs[DDIR_WRITE]) + if (!o->verify_interval || + (o->min_bs[DDIR_WRITE] % o->verify_interval) || + (o->max_bs[DDIR_WRITE] % o->verify_interval)) o->verify_interval = gcd(o->min_bs[DDIR_WRITE], o->max_bs[DDIR_WRITE]); } @@ -816,15 +817,15 @@ static int fixup_options(struct thread_data *td) if (td_ioengine_flagged(td, FIO_PIPEIO)) { log_info("fio: cannot pre-read files with an IO engine" " that isn't seekable. Pre-read disabled.\n"); - ret = warnings_fatal; + ret |= warnings_fatal; } } - if (!o->unit_base) { + if (o->unit_base == N2S_NONE) { if (td_ioengine_flagged(td, FIO_BIT_BASED)) - o->unit_base = 1; + o->unit_base = N2S_BITPERSEC; else - o->unit_base = 8; + o->unit_base = N2S_BYTEPERSEC; } #ifndef FIO_HAVE_ANY_FALLOCATE @@ -840,7 +841,7 @@ static int fixup_options(struct thread_data *td) " this warning\n"); o->fsync_blocks = o->fdatasync_blocks; o->fdatasync_blocks = 0; - ret = warnings_fatal; + ret |= warnings_fatal; } #endif @@ -853,7 +854,7 @@ static int fixup_options(struct thread_data *td) log_err("fio: Windows does not support direct or non-buffered io with" " the synchronous ioengines. Use the 'windowsaio' ioengine" " with 'direct=1' and 'iodepth=1' instead.\n"); - ret = 1; + ret |= 1; } #endif @@ -886,7 +887,7 @@ static int fixup_options(struct thread_data *td) if (o->size && o->size < td_min_bs(td)) { log_err("fio: size too small, must not be less than minimum block size: %llu < %u\n", (unsigned long long) o->size, td_min_bs(td)); - ret = 1; + ret |= 1; } /* @@ -903,7 +904,7 @@ static int fixup_options(struct thread_data *td) if (td_ioengine_flagged(td, FIO_NOEXTEND) && o->file_append) { log_err("fio: can't append/extent with IO engine %s\n", td->io_ops->name); - ret = 1; + ret |= 1; } if (fio_option_is_set(o, gtod_cpu)) { @@ -920,7 +921,7 @@ static int fixup_options(struct thread_data *td) log_err("fio: block error histogram only available " "with a single file per job, but %d files " "provided\n", o->nr_files); - ret = 1; + ret |= 1; } if (fio_option_is_set(o, clat_percentiles) && @@ -934,9 +935,14 @@ static int fixup_options(struct thread_data *td) o->lat_percentiles && o->clat_percentiles) { log_err("fio: lat_percentiles and clat_percentiles are " "mutually exclusive\n"); - ret = 1; + ret |= 1; } + if (o->disable_lat) + o->lat_percentiles = 0; + if (o->disable_clat) + o->clat_percentiles = 0; + /* * Fix these up to be nsec internally */ @@ -979,23 +985,26 @@ 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]; int i; /* * trimwrite is special in that we need to generate the same * offsets to get the "write after trim" effect. If we are * using bssplit to set buffer length distributions, ensure that - * we seed the trim and write generators identically. + * we seed the trim and write generators identically. Ditto for + * verify, read and writes must have the same seed, if we are doing + * read verify. */ - if (td_trimwrite(td)) { - init_rand_seed(&td->bsrange_state[DDIR_READ], td->rand_seeds[FIO_RAND_BS_OFF], use64); - init_rand_seed(&td->bsrange_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_BS1_OFF], use64); - init_rand_seed(&td->bsrange_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_BS1_OFF], use64); - } else { - init_rand_seed(&td->bsrange_state[DDIR_READ], td->rand_seeds[FIO_RAND_BS_OFF], use64); - init_rand_seed(&td->bsrange_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_BS1_OFF], use64); - init_rand_seed(&td->bsrange_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_BS2_OFF], use64); - } + if (td->o.verify != VERIFY_NONE) + write_seed = read_seed; + if (td_trimwrite(td)) + trim_seed = write_seed; + init_rand_seed(&td->bsrange_state[DDIR_READ], read_seed, 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->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF], false); @@ -1064,6 +1073,9 @@ int ioengine_load(struct thread_data *td) } if (td->io_ops) { + struct ioengine_ops *ops; + void *dlhandle; + /* An engine is loaded, but the requested ioengine * may have changed. */ @@ -1072,6 +1084,22 @@ int ioengine_load(struct thread_data *td) return 0; } + /* + * Name of file and engine may be different, load ops + * for this name and see if they match. If they do, then + * the engine is unchanged. + */ + dlhandle = td->io_ops_dlhandle; + ops = load_ioengine(td); + if (ops == td->io_ops && dlhandle == td->io_ops_dlhandle) { + if (dlhandle) + dlclose(dlhandle); + return 0; + } + + if (dlhandle && dlhandle != td->io_ops_dlhandle) + dlclose(dlhandle); + /* Unload the old engine. */ free_ioengine(td); } @@ -1147,7 +1175,7 @@ static void init_flags(struct thread_data *td) fio_option_is_set(o, zero_buffers))) td->flags |= TD_F_SCRAMBLE_BUFFERS; if (o->verify != VERIFY_NONE) - td->flags |= TD_F_VER_NONE; + td->flags |= TD_F_DO_VERIFY; if (o->verify_async || o->io_submit_mode == IO_MODE_OFFLOAD) td->flags |= TD_F_NEED_LOCK; @@ -1416,6 +1444,11 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, } } + if (setup_random_seeds(td)) { + td_verror(td, errno, "setup_random_seeds"); + goto err; + } + if (fixup_options(td)) goto err; @@ -1441,12 +1474,13 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, f->real_file_size = -1ULL; } - td->mutex = fio_mutex_init(FIO_MUTEX_LOCKED); + td->sem = fio_sem_init(FIO_SEM_LOCKED); td->ts.clat_percentiles = o->clat_percentiles; td->ts.lat_percentiles = o->lat_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; for (i = 0; i < DDIR_RWDIR_CNT; i++) { td->ts.clat_stat[i].min_val = ULONG_MAX; @@ -1455,6 +1489,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, td->ts.bw_stat[i].min_val = ULONG_MAX; td->ts.iops_stat[i].min_val = ULONG_MAX; } + td->ts.sync_stat.min_val = ULONG_MAX; td->ddir_seq_nr = o->ddir_seq_nr; if ((o->stonewall || o->new_group) && prev_group_jobs) { @@ -1469,11 +1504,6 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, td->groupid = groupid; prev_group_jobs++; - if (setup_random_seeds(td)) { - td_verror(td, errno, "setup_random_seeds"); - goto err; - } - if (setup_rate(td)) goto err; @@ -1558,7 +1588,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, p.avg_msec = min(o->log_avg_msec, o->bw_avg_time); else o->bw_avg_time = p.avg_msec; - + p.hist_msec = o->log_hist_msec; p.hist_coarseness = o->log_hist_coarseness; @@ -1589,7 +1619,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, p.avg_msec = min(o->log_avg_msec, o->iops_avg_time); else o->iops_avg_time = p.avg_msec; - + p.hist_msec = o->log_hist_msec; p.hist_coarseness = o->log_hist_coarseness; @@ -1931,7 +1961,8 @@ static int __parse_jobs_ini(struct thread_data *td, if (p[0] == '[') { if (nested) { log_err("No new sections in included files\n"); - return 1; + ret = 1; + goto out; } skip_fgets = 1; @@ -2062,7 +2093,7 @@ static int fill_def_thread(void) static void show_debug_categories(void) { #ifdef FIO_INC_DEBUG - struct debug_level *dl = &debug_levels[0]; + const struct debug_level *dl = &debug_levels[0]; int curlen, first = 1; curlen = 0; @@ -2152,7 +2183,7 @@ static void usage(const char *name) } #ifdef FIO_INC_DEBUG -struct debug_level debug_levels[] = { +const struct debug_level debug_levels[] = { { .name = "process", .help = "Process creation/exit logging", .shift = FD_PROCESS, @@ -2230,7 +2261,7 @@ struct debug_level debug_levels[] = { static int set_debug(const char *string) { - struct debug_level *dl; + const struct debug_level *dl; char *p = (char *) string; char *opt; int i;