#include "blktrace_api.h"
#include "oslib/linux-dev-lookup.h"
+struct file_cache {
+ unsigned int maj;
+ unsigned int min;
+ unsigned int fileno;
+};
+
/*
* Just discard the pdu by seeking past it.
*/
flist_add_tail(&ipo->list, &td->io_log_list);
}
-static int trace_add_file(struct thread_data *td, __u32 device)
+static int trace_add_file(struct thread_data *td, __u32 device,
+ struct file_cache *cache)
{
- static unsigned int last_maj, last_min, last_fileno;
unsigned int maj = FMAJOR(device);
unsigned int min = FMINOR(device);
struct fio_file *f;
char dev[256];
unsigned int i;
- if (last_maj == maj && last_min == min)
- return last_fileno;
+ if (cache->maj == maj && cache->min == min)
+ return cache->fileno;
- last_maj = maj;
- last_min = min;
+ cache->maj = maj;
+ cache->min = min;
/*
* check for this file in our list
*/
for_each_file(td, f, i)
if (f->major == maj && f->minor == min) {
- last_fileno = f->fileno;
- return last_fileno;
+ cache->fileno = f->fileno;
+ return cache->fileno;
}
strcpy(dev, "/dev");
td->files[fileno]->major = maj;
td->files[fileno]->minor = min;
trace_add_open_close_event(td, fileno, FIO_LOG_OPEN_FILE);
- last_fileno = fileno;
+ cache->fileno = fileno;
}
- return last_fileno;
+ return cache->fileno;
}
static void t_bytes_align(struct thread_options *o, struct blk_io_trace *t)
static bool handle_trace_discard(struct thread_data *td,
struct blk_io_trace *t,
unsigned long long ttime,
- unsigned long *ios, unsigned long long *bs)
+ unsigned long *ios, unsigned long long *bs,
+ struct file_cache *cache)
{
struct io_piece *ipo;
int fileno;
ipo = calloc(1, sizeof(*ipo));
init_ipo(ipo);
- fileno = trace_add_file(td, t->device);
+ fileno = trace_add_file(td, t->device, cache);
ios[DDIR_TRIM]++;
if (t->bytes > bs[DDIR_TRIM])
static bool handle_trace_fs(struct thread_data *td, struct blk_io_trace *t,
unsigned long long ttime, unsigned long *ios,
- unsigned long long *bs)
+ unsigned long long *bs, struct file_cache *cache)
{
int rw;
int fileno;
- fileno = trace_add_file(td, t->device);
+ fileno = trace_add_file(td, t->device, cache);
rw = (t->action & BLK_TC_ACT(BLK_TC_WRITE)) != 0;
}
static bool handle_trace_flush(struct thread_data *td, struct blk_io_trace *t,
- unsigned long long ttime, unsigned long *ios)
+ unsigned long long ttime, unsigned long *ios,
+ struct file_cache *cache)
{
struct io_piece *ipo;
int fileno;
ipo = calloc(1, sizeof(*ipo));
init_ipo(ipo);
- fileno = trace_add_file(td, t->device);
+ fileno = trace_add_file(td, t->device, cache);
ipo->delay = ttime / 1000;
ipo->ddir = DDIR_SYNC;
* due to internal workings of the block layer.
*/
static bool queue_trace(struct thread_data *td, struct blk_io_trace *t,
- unsigned long *ios, unsigned long long *bs)
+ unsigned long *ios, unsigned long long *bs,
+ struct file_cache *cache)
{
- static unsigned long long last_ttime;
+ unsigned long long *last_ttime = &td->io_log_blktrace_last_ttime;
unsigned long long delay = 0;
if ((t->action & 0xffff) != __BLK_TA_QUEUE)
return false;
if (!(t->action & BLK_TC_ACT(BLK_TC_NOTIFY))) {
- if (!last_ttime || td->o.no_stall)
+ if (!*last_ttime || td->o.no_stall || t->time < *last_ttime)
delay = 0;
else if (td->o.replay_time_scale == 100)
- delay = t->time - last_ttime;
+ delay = t->time - *last_ttime;
else {
- double tmp = t->time - last_ttime;
+ double tmp = t->time - *last_ttime;
double scale;
scale = (double) 100.0 / (double) td->o.replay_time_scale;
tmp *= scale;
delay = tmp;
}
- last_ttime = t->time;
+ *last_ttime = t->time;
}
t_bytes_align(&td->o, t);
if (t->action & BLK_TC_ACT(BLK_TC_NOTIFY))
return handle_trace_notify(t);
else if (t->action & BLK_TC_ACT(BLK_TC_DISCARD))
- return handle_trace_discard(td, t, delay, ios, bs);
+ return handle_trace_discard(td, t, delay, ios, bs, cache);
else if (t->action & BLK_TC_ACT(BLK_TC_FLUSH))
- return handle_trace_flush(td, t, delay, ios);
+ return handle_trace_flush(td, t, delay, ios, cache);
else
- return handle_trace_fs(td, t, delay, ios, bs);
+ return handle_trace_fs(td, t, delay, ios, bs, cache);
}
static void byteswap_trace(struct blk_io_trace *t)
goto err;
}
td->io_log_blktrace_swap = need_swap;
+ td->io_log_blktrace_last_ttime = 0;
td->o.size = 0;
free_release_files(td);
bool read_blktrace(struct thread_data* td)
{
struct blk_io_trace t;
+ struct file_cache cache = { };
unsigned long ios[DDIR_RWDIR_SYNC_CNT] = { };
unsigned long long rw_bs[DDIR_RWDIR_CNT] = { };
unsigned long skipped_writes;
}
}
- if (!queue_trace(td, &t, ios, rw_bs))
+ if (!queue_trace(td, &t, ios, rw_bs, &cache))
continue;
if (td->o.read_iolog_chunked) {
td->o.max_bs[DDIR_TRIM] = rw_bs[DDIR_TRIM];
}
- /*
- * We need to do direct/raw ios to the device, to avoid getting
- * read-ahead in our way. But only do so if the minimum block size
- * is a multiple of 4k, otherwise we don't know if it's safe to do so.
- */
- if (!fio_option_is_set(&td->o, odirect) && !(td_min_bs(td) & 4095))
- td->o.odirect = 1;
-
/*
* If depth wasn't manually set, use probed depth
*/