static int iolog_flush(struct io_log *log);
static const char iolog_ver2[] = "fio version 2 iolog";
+static const char iolog_ver3[] = "fio version 3 iolog";
void queue_io_piece(struct thread_data *td, struct io_piece *ipo)
{
f = td->files[ipo->fileno];
+ if (ipo->delay)
+ iolog_delay(td, ipo->delay);
+ if (fio_fill_issue_time(td))
+ fio_gettime(&td->last_issue, NULL);
switch (ipo->file_action) {
case FIO_LOG_OPEN_FILE:
if (td->o.replay_redirect && fio_file_open(f)) {
case FIO_LOG_UNLINK_FILE:
td_io_unlink_file(td, f);
break;
+ case FIO_LOG_ADD_FILE:
+ /*
+ * Nothing to do
+ */
+ break;
default:
log_err("fio: bad file action %d\n", ipo->file_action);
break;
return 1;
}
-static bool read_iolog2(struct thread_data *td);
+static bool read_iolog(struct thread_data *td);
+
+unsigned long long delay_since_ttime(const struct thread_data *td,
+ unsigned long long time)
+{
+ double tmp;
+ double scale;
+ const unsigned long long *last_ttime = &td->io_log_last_ttime;
+
+ if (!*last_ttime || td->o.no_stall || time < *last_ttime)
+ return 0;
+ else if (td->o.replay_time_scale == 100)
+ return time - *last_ttime;
+
+
+ scale = (double) 100.0 / (double) td->o.replay_time_scale;
+ tmp = time - *last_ttime;
+ return tmp * scale;
+}
int read_iolog_get(struct thread_data *td, struct io_u *io_u)
{
if (!read_blktrace(td))
return 1;
} else {
- if (!read_iolog2(td))
+ if (!read_iolog(td))
return 1;
}
}
return items_to_fetch;
}
+#define io_act(_td, _r) (((_td)->io_log_version == 3 && (r) == 5) || \
+ ((_td)->io_log_version == 2 && (r) == 4))
+#define file_act(_td, _r) (((_td)->io_log_version == 3 && (r) == 3) || \
+ ((_td)->io_log_version == 2 && (r) == 2))
+
/*
- * Read version 2 iolog data. It is enhanced to include per-file logging,
+ * Read version 2 and 3 iolog data. It is enhanced to include per-file logging,
* syncs, etc.
*/
-static bool read_iolog2(struct thread_data *td)
+static bool read_iolog(struct thread_data *td)
{
unsigned long long offset;
unsigned int bytes;
+ unsigned long long delay = 0;
int reads, writes, waits, fileno = 0, file_action = 0; /* stupid gcc */
char *rfname, *fname, *act;
char *str, *p;
while ((p = fgets(str, 4096, td->io_log_rfile)) != NULL) {
struct io_piece *ipo;
int r;
+ unsigned long long ttime;
- r = sscanf(p, "%256s %256s %llu %u", rfname, act, &offset,
- &bytes);
+ if (td->io_log_version == 3) {
+ r = sscanf(p, "%llu %256s %256s %llu %u", &ttime, rfname, act,
+ &offset, &bytes);
+ delay = delay_since_ttime(td, ttime);
+ td->io_log_last_ttime = ttime;
+ /*
+ * "wait" is not allowed with version 3
+ */
+ if (!strcmp(act, "wait")) {
+ log_err("iolog: ignoring wait command with"
+ " version 3 for file %s\n", fname);
+ continue;
+ }
+ } else /* version 2 */
+ r = sscanf(p, "%256s %256s %llu %u", rfname, act, &offset, &bytes);
if (td->o.replay_redirect)
fname = td->o.replay_redirect;
- if (r == 4) {
+ if (io_act(td, r)) {
/*
* Check action first
*/
continue;
}
fileno = get_fileno(td, fname);
- } else if (r == 2) {
+ } else if (file_act(td, r)) {
rw = DDIR_INVAL;
if (!strcmp(act, "add")) {
if (td->o.replay_redirect &&
fileno = add_file(td, fname, td->subjob_number, 1);
file_action = FIO_LOG_ADD_FILE;
}
- continue;
} else if (!strcmp(act, "open")) {
fileno = get_fileno(td, fname);
file_action = FIO_LOG_OPEN_FILE;
continue;
}
} else {
- log_err("bad iolog2: %s\n", p);
+ log_err("bad iolog%d: %s\n", td->io_log_version, p);
continue;
}
ipo = calloc(1, sizeof(*ipo));
init_ipo(ipo);
ipo->ddir = rw;
+ if (td->io_log_version == 3)
+ ipo->delay = delay;
if (rw == DDIR_WAIT) {
ipo->delay = offset;
} else {
}
/*
- * version 2 of the iolog stores a specific string as the
+ * versions 2 and 3 of the iolog store a specific string as the
* first line, check for that
*/
- if (!strncmp(iolog_ver2, buffer, strlen(iolog_ver2))) {
- free_release_files(td);
- td->io_log_rfile = f;
- return read_iolog2(td);
+ if (!strncmp(iolog_ver2, buffer, strlen(iolog_ver2)))
+ td->io_log_version = 2;
+ else if (!strncmp(iolog_ver3, buffer, strlen(iolog_ver3)))
+ td->io_log_version = 3;
+ else {
+ log_err("fio: iolog version 1 is no longer supported\n");
+ fclose(f);
+ return false;
}
- log_err("fio: iolog version 1 is no longer supported\n");
- fclose(f);
- return false;
+ free_release_files(td);
+ td->io_log_rfile = f;
+ return read_iolog(td);
}
/*