Some options are in seconds, if no units are given. These include
runtime/timeout, startdelay, and ramp_time. Handle this
appropriately. Internally it should all be microseconds now, it's
just the conversion factor.
Signed-off-by: Jens Axboe <axboe@fb.com>
str String. This is a sequence of alpha characters.
time Integer with possible time suffix. In seconds unless otherwise
specified, use eg 10m for 10 minutes. Accepts s/m/h for seconds,
str String. This is a sequence of alpha characters.
time Integer with possible time suffix. In seconds unless otherwise
specified, use eg 10m for 10 minutes. Accepts s/m/h for seconds,
+ minutes, and hours, and accepts 'ms' (or 'msec') for milliseconds,
+ and 'us' (or 'usec') for microseconds.
int SI integer. A whole number value, which may contain a suffix
describing the base of the number. Accepted suffixes are k/m/g/t/p,
meaning kilo, mega, giga, tera, and peta. The suffix is not case
int SI integer. A whole number value, which may contain a suffix
describing the base of the number. Accepted suffixes are k/m/g/t/p,
meaning kilo, mega, giga, tera, and peta. The suffix is not case
return 0;
if (!td->o.timeout)
return 0;
return 0;
if (!td->o.timeout)
return 0;
- if (mtime_since(&td->epoch, t) >= td->o.timeout )
+ if (utime_since(&td->epoch, t) >= td->o.timeout)
static void run_threads(void)
{
struct thread_data *td;
static void run_threads(void)
{
struct thread_data *td;
unsigned int i, todo, nr_running, m_rate, t_rate, nr_started;
unsigned int i, todo, nr_running, m_rate, t_rate, nr_started;
if (fio_gtod_offload && fio_start_gtod_thread())
return;
if (fio_gtod_offload && fio_start_gtod_thread())
return;
}
if (td->o.start_delay) {
}
if (td->o.start_delay) {
- spent = mtime_since_genesis();
+ spent = utime_since_genesis();
if (td->o.start_delay > spent)
continue;
if (td->o.start_delay > spent)
continue;
unsigned long long bytes_total, bytes_done;
unsigned long eta_sec = 0;
unsigned long elapsed;
unsigned long long bytes_total, bytes_done;
unsigned long eta_sec = 0;
unsigned long elapsed;
elapsed = (mtime_since_now(&td->epoch) + 999) / 1000;
elapsed = (mtime_since_now(&td->epoch) + 999) / 1000;
+ timeout = td->o.timeout / 1000000UL;
bytes_total = td->total_io_size;
bytes_total = td->total_io_size;
perc = 1.0;
if (td->o.time_based) {
perc = 1.0;
if (td->o.time_based) {
- perc_t = (double) elapsed /
- (double) (td->o.timeout / 1000);
+ perc_t = (double) elapsed / (double) timeout;
if (perc_t < perc)
perc = perc_t;
}
if (perc_t < perc)
perc = perc_t;
}
eta_sec = (unsigned long) (elapsed * (1.0 / perc)) - elapsed;
if (td->o.timeout &&
eta_sec = (unsigned long) (elapsed * (1.0 / perc)) - elapsed;
if (td->o.timeout &&
- eta_sec > ( (td->o.timeout / 1000) + done_secs - elapsed))
- eta_sec = (td->o.timeout / 1000) + done_secs
- - elapsed;
+ eta_sec > (timeout + done_secs - elapsed))
+ eta_sec = timeout + done_secs - elapsed;
} else if (td->runstate == TD_NOT_CREATED || td->runstate == TD_CREATED
|| td->runstate == TD_INITIALIZED
|| td->runstate == TD_SETTING_UP
} else if (td->runstate == TD_NOT_CREATED || td->runstate == TD_CREATED
|| td->runstate == TD_INITIALIZED
|| td->runstate == TD_SETTING_UP
* if given, otherwise assume it'll run at the specified rate.
*/
if (td->o.timeout) {
* if given, otherwise assume it'll run at the specified rate.
*/
if (td->o.timeout) {
- t_eta = (td->o.timeout + td->o.start_delay +
- td->o.ramp_time ) / 1000;
+ uint64_t timeout = td->o.timeout;
+ uint64_t start_delay = td->o.start_delay;
+ uint64_t ramp_time = td->o.ramp_time;
+
+ t_eta = timeout + start_delay + ramp_time;
+ t_eta /= 1000000ULL;
if (in_ramp_time(td)) {
unsigned long ramp_left;
if (in_ramp_time(td)) {
unsigned long ramp_left;
rate_bytes = ddir_rw_sum(td->o.rate);
if (rate_bytes) {
r_eta = (bytes_total / 1024) / rate_bytes;
rate_bytes = ddir_rw_sum(td->o.rate);
if (rate_bytes) {
r_eta = (bytes_total / 1024) / rate_bytes;
- r_eta += td->o.start_delay / 1000;
+ r_eta += (td->o.start_delay / 1000000ULL);
values. Specifying '30GiB' will get you 30*1000^3 bytes.
When specifying times the default suffix meaning changes, still denoting the
base unit of the value, but accepted suffixes are 'D' (days), 'H' (hours), 'M'
values. Specifying '30GiB' will get you 30*1000^3 bytes.
When specifying times the default suffix meaning changes, still denoting the
base unit of the value, but accepted suffixes are 'D' (days), 'H' (hours), 'M'
-(minutes), 'S' Seconds, 'ms' milli seconds. Time values without a unit specify
-seconds.
+(minutes), 'S' Seconds, 'ms' (or msec) milli seconds, 'us' (or 'usec') micro
+seconds. Time values without a unit specify seconds.
The suffixes are not case sensitive.
.TP
.I bool
The suffixes are not case sensitive.
.TP
.I bool
case 'E': {
long long t = 0;
case 'E': {
long long t = 0;
- if (str_to_decimal(optarg, &t, 0, NULL)) {
+ if (str_to_decimal(optarg, &t, 0, NULL, 1)) {
log_err("fio: failed parsing eta time %s\n", optarg);
exit_val = 1;
do_exit++;
log_err("fio: failed parsing eta time %s\n", optarg);
exit_val = 1;
do_exit++;
case 'L': {
long long val;
case 'L': {
long long val;
- if (check_str_time(optarg, &val)) {
+ if (check_str_time(optarg, &val, 1)) {
log_err("fio: failed parsing time %s\n", optarg);
do_exit++;
exit_val = 1;
log_err("fio: failed parsing time %s\n", optarg);
do_exit++;
exit_val = 1;
- if (str_to_decimal(fname, &val, 1, o)) {
+ if (str_to_decimal(fname, &val, 1, o, 0)) {
log_err("fio: bssplit conversion failed\n");
free(bssplit);
return 1;
log_err("fio: bssplit conversion failed\n");
free(bssplit);
return 1;
- if (str_to_decimal(nr, &val, 1, o)) {
+ if (str_to_decimal(nr, &val, 1, o, 0)) {
log_err("fio: rw postfix parsing failed\n");
free(nr);
return 1;
log_err("fio: rw postfix parsing failed\n");
free(nr);
return 1;
.off2 = td_var_offset(start_delay_high),
.help = "Only start job when this period has passed",
.def = "0",
.off2 = td_var_offset(start_delay_high),
.help = "Only start job when this period has passed",
.def = "0",
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_RUNTIME,
},
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_RUNTIME,
},
.off1 = td_var_offset(timeout),
.help = "Stop workload when this amount of time has passed",
.def = "0",
.off1 = td_var_offset(timeout),
.help = "Stop workload when this amount of time has passed",
.def = "0",
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_RUNTIME,
},
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_RUNTIME,
},
.type = FIO_OPT_STR_VAL_TIME,
.off1 = td_var_offset(ramp_time),
.help = "Ramp up time before measuring performance",
.type = FIO_OPT_STR_VAL_TIME,
.off1 = td_var_offset(ramp_time),
.help = "Ramp up time before measuring performance",
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_RUNTIME,
},
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_RUNTIME,
},
-static unsigned long long get_mult_time(const char *str, int len)
+static unsigned long long get_mult_time(const char *str, int len,
+ int is_seconds)
{
const char *p = str;
char *c;
{
const char *p = str;
char *c;
- if (!isalpha((int) *p))
- return mult;
+ if (!isalpha((int) *p)) {
+ if (is_seconds)
+ return 1000000UL;
+ else
+ return 1;
+ }
c = strdup(p);
for (int i = 0; i < strlen(c); i++)
c = strdup(p);
for (int i = 0; i < strlen(c); i++)
/*
* convert string into decimal value, noting any size suffix
*/
/*
* convert string into decimal value, noting any size suffix
*/
-int str_to_decimal(const char *str, long long *val, int kilo, void *data)
+int str_to_decimal(const char *str, long long *val, int kilo, void *data,
+ int is_seconds)
else
*val *= mult;
} else
else
*val *= mult;
} else
- *val *= get_mult_time(str, len);
+ *val *= get_mult_time(str, len, is_seconds);
return 0;
}
int check_str_bytes(const char *p, long long *val, void *data)
{
return 0;
}
int check_str_bytes(const char *p, long long *val, void *data)
{
- return str_to_decimal(p, val, 1, data);
+ return str_to_decimal(p, val, 1, data, 0);
-int check_str_time(const char *p, long long *val)
+int check_str_time(const char *p, long long *val, int is_seconds)
- return str_to_decimal(p, val, 0, NULL);
+ return str_to_decimal(p, val, 0, NULL, is_seconds);
}
void strip_blank_front(char **p)
}
void strip_blank_front(char **p)
- if (!str_to_decimal(str, &__val, 1, data)) {
+ if (!str_to_decimal(str, &__val, 1, data, 0)) {
*val = __val;
return 0;
}
*val = __val;
return 0;
}
- ret = check_str_time(tmp, &ull);
+ ret = check_str_time(tmp, &ull, o->is_seconds);
else
ret = check_str_bytes(tmp, &ull, data);
else
ret = check_str_bytes(tmp, &ull, data);
unsigned int category; /* what type of option */
unsigned int group; /* who to group with */
void *gui_data;
unsigned int category; /* what type of option */
unsigned int group; /* who to group with */
void *gui_data;
+ int is_seconds; /* time value with seconds base */
};
typedef int (str_cb_fn)(void *, char *);
};
typedef int (str_cb_fn)(void *, char *);
extern void strip_blank_front(char **);
extern void strip_blank_end(char *);
extern void strip_blank_front(char **);
extern void strip_blank_end(char *);
-extern int str_to_decimal(const char *, long long *, int, void *);
+extern int str_to_decimal(const char *, long long *, int, void *, int);
extern int check_str_bytes(const char *p, long long *val, void *data);
extern int check_str_bytes(const char *p, long long *val, void *data);
-extern int check_str_time(const char *p, long long *val);
+extern int check_str_time(const char *p, long long *val, int);
extern int str_to_float(const char *str, double *val);
/*
extern int str_to_float(const char *str, double *val);
/*
return mtime_since_now(&genesis);
}
return mtime_since_now(&genesis);
}
+uint64_t utime_since_genesis(void)
+{
+ return utime_since_now(&genesis);
+}
+
int in_ramp_time(struct thread_data *td)
{
return td->o.ramp_time && !td->ramp_time_over;
int in_ramp_time(struct thread_data *td)
{
return td->o.ramp_time && !td->ramp_time_over;
return 1;
fio_gettime(&tv, NULL);
return 1;
fio_gettime(&tv, NULL);
- if (mtime_since(&td->epoch, &tv) >= td->o.ramp_time ) {
+ if (utime_since(&td->epoch, &tv) >= td->o.ramp_time) {
td->ramp_time_over = 1;
reset_all_stats(td);
td_set_runstate(td, TD_RAMP);
td->ramp_time_over = 1;
reset_all_stats(td);
td_set_runstate(td, TD_RAMP);
extern uint64_t mtime_since_now(struct timeval *);
extern uint64_t time_since_now(struct timeval *);
extern uint64_t mtime_since_genesis(void);
extern uint64_t mtime_since_now(struct timeval *);
extern uint64_t time_since_now(struct timeval *);
extern uint64_t mtime_since_genesis(void);
+extern uint64_t utime_since_genesis(void);
extern void usec_spin(unsigned int);
extern void usec_sleep(struct thread_data *, unsigned long);
extern void fill_start_time(struct timeval *);
extern void usec_spin(unsigned int);
extern void usec_sleep(struct thread_data *, unsigned long);
extern void fill_start_time(struct timeval *);