#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
-#include <sys/stat.h>
+#include <dlfcn.h>
+#ifdef CONFIG_VALGRIND_DEV
+#include <valgrind/drd.h>
+#else
+#define DRD_IGNORE_VAR(x) do { } while (0)
+#endif
#include "fio.h"
#ifndef FIO_NO_HAVE_SHM_H
int exitall_on_terminate = 0;
int output_format = FIO_OUTPUT_NORMAL;
int eta_print = FIO_ETA_AUTO;
+unsigned int eta_interval_msec = 1000;
int eta_new_line = 0;
FILE *f_out = NULL;
FILE *f_err = NULL;
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;
.has_arg = required_argument,
.val = 'e' | FIO_CLIENT_FLAG,
},
+ {
+ .name = (char *) "eta-interval",
+ .has_arg = required_argument,
+ .val = 'O' | FIO_CLIENT_FLAG,
+ },
{
.name = (char *) "eta-newline",
.has_arg = required_argument,
if (threads) {
flow_exit();
fio_debug_jobp = NULL;
+ fio_warned = NULL;
free_threads_shm();
}
*/
static int setup_thread_area(void)
{
+ int i;
+
if (threads)
return 0;
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);
#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();
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]);
}
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
*/
}
if (td->io_ops) {
+ struct ioengine_ops *ops;
+ void *dlhandle;
+
/* An engine is loaded, but the requested ioengine
* may have changed.
*/
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);
}
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;
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) {
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;
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;
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;
printf(" --trigger=cmd\t\tSet this command as local trigger\n");
printf(" --trigger-remote=cmd\tSet this command as remote trigger\n");
printf(" --aux-path=path\tUse this path for fio state generated files\n");
- printf("\nFio was written by Jens Axboe <jens.axboe@oracle.com>");
- printf("\n Jens Axboe <jaxboe@fusionio.com>");
- printf("\n Jens Axboe <axboe@fb.com>\n");
+ printf("\nFio was written by Jens Axboe <axboe@kernel.dk>\n");
}
#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,
static int set_debug(const char *string)
{
- struct debug_level *dl;
+ const struct debug_level *dl;
char *p = (char *) string;
char *opt;
int i;
log_err("fio: failed parsing eta time %s\n", optarg);
exit_val = 1;
do_exit++;
+ break;
}
eta_new_line = t / 1000;
+ if (!eta_new_line) {
+ log_err("fio: eta new line time too short\n");
+ exit_val = 1;
+ do_exit++;
+ }
+ break;
+ }
+ case 'O': {
+ long long t = 0;
+
+ if (check_str_time(optarg, &t, 1)) {
+ log_err("fio: failed parsing eta interval %s\n", optarg);
+ exit_val = 1;
+ do_exit++;
+ break;
+ }
+ eta_interval_msec = t / 1000;
+ if (eta_interval_msec < DISK_UTIL_MSEC) {
+ log_err("fio: eta interval time too short (%umsec min)\n", DISK_UTIL_MSEC);
+ exit_val = 1;
+ do_exit++;
+ }
break;
}
case 'd':