This patch tries to address issues found when compiling fio with clang's
undefined behaviour sanitizer on 32 bit Linux. While this generated many
false positives it did identify a number of subtle issues when
rates/amounts/time calculations went above 32 bit values.
The following job was used:
[global]
time_based
runtime=180m
bs=256k
rw=randrw
norandommap
rate=512M
ioengine=null
direct=1
iodepth=8
thread
numjobs=10
ramp_time=20m
[null]
size=1P
It should fix https://github.com/axboe/fio/issues/270 because various 32
bit ETA variables were overflowing due to the microsecond arithmetic
being done on them (even on 64 bit systems).
This patch should also fix https://github.com/axboe/fio/issues/194 and
https://github.com/axboe/fio/issues/266 because 64 bit Windows is a
LLP64 platform so ints and longs still default to 32 bits.
Signed-off-by: Sitsofe Wheeler <sitsofe@yahoo.com>
/*
* Run over the job map and reap the threads that have exited, if any.
*/
/*
* Run over the job map and reap the threads that have exited, if any.
*/
-static void reap_threads(unsigned int *nr_running, unsigned int *t_rate,
- unsigned int *m_rate)
+static void reap_threads(unsigned int *nr_running, uint64_t *t_rate,
+ uint64_t *m_rate)
{
struct thread_data *td;
unsigned int cputhreads, realthreads, pending;
{
struct thread_data *td;
unsigned int cputhreads, realthreads, pending;
static void run_threads(struct sk_out *sk_out)
{
struct thread_data *td;
static void run_threads(struct sk_out *sk_out)
{
struct thread_data *td;
- unsigned int i, todo, nr_running, m_rate, t_rate, nr_started;
+ unsigned int i, todo, nr_running, nr_started;
+ uint64_t m_rate, t_rate;
uint64_t spent;
if (fio_gtod_offload && fio_start_gtod_thread())
uint64_t spent;
if (fio_gtod_offload && fio_start_gtod_thread())
}
o->rwmix[i] = le32_to_cpu(top->rwmix[i]);
}
o->rwmix[i] = le32_to_cpu(top->rwmix[i]);
- o->rate[i] = le32_to_cpu(top->rate[i]);
- o->ratemin[i] = le32_to_cpu(top->ratemin[i]);
+ o->rate[i] = le64_to_cpu(top->rate[i]);
+ o->ratemin[i] = le64_to_cpu(top->ratemin[i]);
o->rate_iops[i] = le32_to_cpu(top->rate_iops[i]);
o->rate_iops_min[i] = le32_to_cpu(top->rate_iops_min[i]);
o->rate_iops[i] = le32_to_cpu(top->rate_iops[i]);
o->rate_iops_min[i] = le32_to_cpu(top->rate_iops_min[i]);
}
top->rwmix[i] = cpu_to_le32(o->rwmix[i]);
}
top->rwmix[i] = cpu_to_le32(o->rwmix[i]);
- top->rate[i] = cpu_to_le32(o->rate[i]);
- top->ratemin[i] = cpu_to_le32(o->ratemin[i]);
+ top->rate[i] = cpu_to_le64(o->rate[i]);
+ top->ratemin[i] = cpu_to_le64(o->ratemin[i]);
top->rate_iops[i] = cpu_to_le32(o->rate_iops[i]);
top->rate_iops_min[i] = cpu_to_le32(o->rate_iops_min[i]);
top->rate_iops[i] = cpu_to_le32(o->rate_iops[i]);
top->rate_iops_min[i] = cpu_to_le32(o->rate_iops_min[i]);
je->files_open = le32_to_cpu(je->files_open);
for (i = 0; i < DDIR_RWDIR_CNT; i++) {
je->files_open = le32_to_cpu(je->files_open);
for (i = 0; i < DDIR_RWDIR_CNT; i++) {
- je->m_rate[i] = le32_to_cpu(je->m_rate[i]);
- je->t_rate[i] = le32_to_cpu(je->t_rate[i]);
+ je->m_rate[i] = le64_to_cpu(je->m_rate[i]);
+ je->t_rate[i] = le64_to_cpu(je->t_rate[i]);
je->m_iops[i] = le32_to_cpu(je->m_iops[i]);
je->t_iops[i] = le32_to_cpu(je->t_iops[i]);
je->m_iops[i] = le32_to_cpu(je->m_iops[i]);
je->t_iops[i] = le32_to_cpu(je->t_iops[i]);
- je->rate[i] = le32_to_cpu(je->rate[i]);
+ je->rate[i] = le64_to_cpu(je->rate[i]);
je->iops[i] = le32_to_cpu(je->iops[i]);
}
je->iops[i] = le32_to_cpu(je->iops[i]);
}
|| td->runstate == TD_SETTING_UP
|| td->runstate == TD_RAMP
|| td->runstate == TD_PRE_READING) {
|| td->runstate == TD_SETTING_UP
|| td->runstate == TD_RAMP
|| td->runstate == TD_PRE_READING) {
- int t_eta = 0, r_eta = 0;
+ int64_t t_eta = 0, r_eta = 0;
unsigned long long rate_bytes;
/*
unsigned long long rate_bytes;
/*
static void calc_rate(int unified_rw_rep, unsigned long mtime,
unsigned long long *io_bytes,
static void calc_rate(int unified_rw_rep, unsigned long mtime,
unsigned long long *io_bytes,
- unsigned long long *prev_io_bytes, unsigned int *rate)
+ unsigned long long *prev_io_bytes, uint64_t *rate)
{
struct thread_data *td;
int i, unified_rw_rep;
{
struct thread_data *td;
int i, unified_rw_rep;
- unsigned long rate_time, disp_time, bw_avg_time, *eta_secs;
+ uint64_t rate_time, disp_time, bw_avg_time, *eta_secs;
unsigned long long io_bytes[DDIR_RWDIR_CNT];
unsigned long long io_iops[DDIR_RWDIR_CNT];
struct timeval now;
unsigned long long io_bytes[DDIR_RWDIR_CNT];
unsigned long long io_iops[DDIR_RWDIR_CNT];
struct timeval now;
if (!ddir_rw_sum(disp_io_bytes))
fill_start_time(&disp_prev_time);
if (!ddir_rw_sum(disp_io_bytes))
fill_start_time(&disp_prev_time);
- eta_secs = malloc(thread_number * sizeof(unsigned long));
- memset(eta_secs, 0, thread_number * sizeof(unsigned long));
+ eta_secs = malloc(thread_number * sizeof(uint64_t));
+ memset(eta_secs, 0, thread_number * sizeof(uint64_t));
je->elapsed_sec = (mtime_since_genesis() + 999) / 1000;
je->elapsed_sec = (mtime_since_genesis() + 999) / 1000;
* Rate state
*/
uint64_t rate_bps[DDIR_RWDIR_CNT];
* Rate state
*/
uint64_t rate_bps[DDIR_RWDIR_CNT];
- unsigned long rate_next_io_time[DDIR_RWDIR_CNT];
+ uint64_t rate_next_io_time[DDIR_RWDIR_CNT];
unsigned long rate_bytes[DDIR_RWDIR_CNT];
unsigned long rate_blocks[DDIR_RWDIR_CNT];
unsigned long rate_bytes[DDIR_RWDIR_CNT];
unsigned long rate_blocks[DDIR_RWDIR_CNT];
- unsigned long rate_io_issue_bytes[DDIR_RWDIR_CNT];
+ unsigned long long rate_io_issue_bytes[DDIR_RWDIR_CNT];
struct timeval lastrate[DDIR_RWDIR_CNT];
int64_t last_usec;
struct frand_state poisson_state;
struct timeval lastrate[DDIR_RWDIR_CNT];
int64_t last_usec;
struct frand_state poisson_state;
uint64_t utime_since(const struct timeval *s, const struct timeval *e)
{
uint64_t utime_since(const struct timeval *s, const struct timeval *e)
{
sec = e->tv_sec - s->tv_sec;
usec = e->tv_usec - s->tv_usec;
sec = e->tv_sec - s->tv_sec;
usec = e->tv_usec - s->tv_usec;
static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
{
enum fio_ddir odir = ddir ^ 1;
static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
{
enum fio_ddir odir = ddir ^ 1;
+ long usec;
+ uint64_t now;
assert(ddir_rw(ddir));
now = utime_since_now(&td->start);
assert(ddir_rw(ddir));
now = utime_since_now(&td->start);
t.tv_nsec = tv_s.tv_usec * 1000;
t.tv_sec += msecs / 1000;
t.tv_nsec = tv_s.tv_usec * 1000;
t.tv_sec += msecs / 1000;
- t.tv_nsec += ((msecs * 1000000) % 1000000000);
+ t.tv_nsec += ((msecs * 1000000ULL) % 1000000000);
if (t.tv_nsec >= 1000000000) {
t.tv_nsec -= 1000000000;
t.tv_sec++;
if (t.tv_nsec >= 1000000000) {
t.tv_nsec -= 1000000000;
t.tv_sec++;
je->files_open = cpu_to_le32(je->files_open);
for (i = 0; i < DDIR_RWDIR_CNT; i++) {
je->files_open = cpu_to_le32(je->files_open);
for (i = 0; i < DDIR_RWDIR_CNT; i++) {
- je->m_rate[i] = cpu_to_le32(je->m_rate[i]);
- je->t_rate[i] = cpu_to_le32(je->t_rate[i]);
+ je->m_rate[i] = cpu_to_le64(je->m_rate[i]);
+ je->t_rate[i] = cpu_to_le64(je->t_rate[i]);
je->m_iops[i] = cpu_to_le32(je->m_iops[i]);
je->t_iops[i] = cpu_to_le32(je->t_iops[i]);
je->m_iops[i] = cpu_to_le32(je->m_iops[i]);
je->t_iops[i] = cpu_to_le32(je->t_iops[i]);
- je->rate[i] = cpu_to_le32(je->rate[i]);
+ je->rate[i] = cpu_to_le64(je->rate[i]);
je->iops[i] = cpu_to_le32(je->iops[i]);
}
je->iops[i] = cpu_to_le32(je->iops[i]);
}
- uint32_t m_rate[DDIR_RWDIR_CNT], t_rate[DDIR_RWDIR_CNT];
+ uint64_t m_rate[DDIR_RWDIR_CNT], t_rate[DDIR_RWDIR_CNT];
uint32_t m_iops[DDIR_RWDIR_CNT], t_iops[DDIR_RWDIR_CNT];
uint32_t m_iops[DDIR_RWDIR_CNT], t_iops[DDIR_RWDIR_CNT];
- uint32_t rate[DDIR_RWDIR_CNT];
+ uint64_t rate[DDIR_RWDIR_CNT];
uint32_t iops[DDIR_RWDIR_CNT];
uint64_t elapsed_sec;
uint64_t eta_sec;
uint32_t iops[DDIR_RWDIR_CNT];
uint64_t elapsed_sec;
uint64_t eta_sec;
char *exec_prerun;
char *exec_postrun;
char *exec_prerun;
char *exec_postrun;
- unsigned int rate[DDIR_RWDIR_CNT];
- unsigned int ratemin[DDIR_RWDIR_CNT];
+ uint64_t rate[DDIR_RWDIR_CNT];
+ uint64_t ratemin[DDIR_RWDIR_CNT];
unsigned int ratecycle;
unsigned int io_submit_mode;
unsigned int rate_iops[DDIR_RWDIR_CNT];
unsigned int ratecycle;
unsigned int io_submit_mode;
unsigned int rate_iops[DDIR_RWDIR_CNT];
uint8_t exec_prerun[FIO_TOP_STR_MAX];
uint8_t exec_postrun[FIO_TOP_STR_MAX];
uint8_t exec_prerun[FIO_TOP_STR_MAX];
uint8_t exec_postrun[FIO_TOP_STR_MAX];
- uint32_t rate[DDIR_RWDIR_CNT];
- uint32_t ratemin[DDIR_RWDIR_CNT];
+ uint64_t rate[DDIR_RWDIR_CNT];
+ uint64_t ratemin[DDIR_RWDIR_CNT];
uint32_t ratecycle;
uint32_t io_submit_mode;
uint32_t rate_iops[DDIR_RWDIR_CNT];
uint32_t ratecycle;
uint32_t io_submit_mode;
uint32_t rate_iops[DDIR_RWDIR_CNT];