Recent changes (master)
Jens Axboe <[email protected]> Wed, 6 Aug 2025 06:00:02 -0600 (MDT)
| Newsgroups | org.kernel.vger.fio |
|---|---|
| Message-ID | <[email protected]> |
The following changes since commit ef740f7cbe47d5552677fb018b15b4ab1f1de4f4:
t/io_uring_pi: test script for io_uring PI (2025-08-02 09:40:12 -0600)
are available in the Git repository at:
git://git.kernel.dk/fio.git master
for you to fetch changes up to b1b07c8dfbb562a949afd127d693e9c0cb009827:
ioengines: bump version number (2025-08-05 15:56:45 -0600)
----------------------------------------------------------------
Jens Axboe (2):
Merge branch 'verify_inflight' of https://github.com/noclip-code/fio
ioengines: bump version number
Riley Thomasson (5):
verify: make numberio uint64_t
verify: rework write tracking for use with verify_save_state()
verify: plumb inflight write information through verify state
verify: clear inflight log in between loops
verify: add versioning to verify_header
backend.c | 157 +++++++++++++++++++++++++++++++++++++++++--------------
file.h | 7 ---
fio.h | 17 +++++-
io_u.c | 11 +---
io_u.h | 4 +-
ioengines.h | 2 +-
iolog.h | 2 +-
libfio.c | 2 +
t/verify-state.c | 26 ++++-----
verify-state.h | 24 ++++-----
verify.c | 118 ++++++++++++-----------------------------
verify.h | 11 +++-
12 files changed, 202 insertions(+), 179 deletions(-)
---
Diff of recent changes:
diff --git a/backend.c b/backend.c
index 0cdee864..922309a0 100644
--- a/backend.c
+++ b/backend.c
@@ -714,7 +714,7 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
break;
}
- if (verify_state_should_stop(td, io_u)) {
+ if (verify_state_should_stop(td, io_u->numberio)) {
put_io_u(td, io_u);
break;
}
@@ -948,6 +948,102 @@ static void handle_thinktime(struct thread_data *td, enum fio_ddir ddir,
}
}
+/*
+ * Add numberio from io_u to the inflight log.
+ */
+void log_inflight(struct thread_data *td, struct io_u *io_u)
+{
+ int idx, i;
+
+ if (!td->inflight_numberio || io_u->ddir != DDIR_WRITE)
+ return;
+
+ if (io_u->inflight_idx != -1) {
+ log_err("inflight_idx already set: inflight_idx=%d\n",
+ io_u->inflight_idx);
+ abort();
+ }
+
+ if (td->inflight_issued != io_u->numberio) {
+ log_err("inflight_issued does not match: numberio=%"PRIu64", inflight_issued=%"PRIu64"\n",
+ io_u->numberio, td->inflight_issued);
+ abort();
+ }
+
+ /* Walk the inflight list until we find a free slot. */
+ idx = td->next_inflight_numberio_idx;
+ for (i = 0; i < td->o.iodepth; i++) {
+ if (td->inflight_numberio[idx] == INVALID_NUMBERIO) {
+ /*
+ * The order here is important - we must "protect" this write in the
+ * inflight list before making it visible in inflight_issued.
+ */
+ atomic_store_release(&td->inflight_numberio[idx], io_u->numberio);
+ td->next_inflight_numberio_idx = (idx + 1) % td->o.iodepth;
+ io_u->inflight_idx = idx;
+
+ atomic_store_release(&td->inflight_issued, io_u->numberio + 1);
+ dprint(FD_VERIFY, "log_inflight: numberio=%"PRIu64", inflight_idx=%d\n",
+ io_u->numberio, idx);
+ return;
+ }
+ idx = (idx + 1) % td->o.iodepth;
+ }
+
+ log_err("failed to allocate inflight slot: next_inflight_numberio_idx=%u\n",
+ td->next_inflight_numberio_idx);
+ abort();
+}
+
+/*
+ * Invalidate inflight log entry.
+ */
+void invalidate_inflight(struct thread_data *td, struct io_u *io_u)
+{
+ if (!td->inflight_numberio ||
+ io_u->ddir != DDIR_WRITE ||
+ io_u->inflight_idx == -1) {
+ return;
+ }
+
+ dprint(FD_VERIFY, "invalidate_inflight: numberio=%"PRIu64", inflight_idx=%d\n",
+ io_u->numberio, io_u->inflight_idx);
+
+ if (td->inflight_numberio[io_u->inflight_idx] == INVALID_NUMBERIO) {
+ log_err("inflight entry already invalid: numberio=%"PRIu64", inflight_idx=%d\n",
+ io_u->numberio, io_u->inflight_idx);
+ abort();
+ } else if (td->inflight_numberio[io_u->inflight_idx] != io_u->numberio) {
+ log_err("inflight entry numberio does not match: expected numberio=%"PRIu64", observed numberio=%"PRIu64", inflight_idx=%d\n",
+ io_u->numberio, td->inflight_numberio[io_u->inflight_idx], io_u->inflight_idx);
+ abort();
+ }
+
+ atomic_store_release(&td->inflight_numberio[io_u->inflight_idx], INVALID_NUMBERIO);
+ io_u->inflight_idx = -1;
+}
+
+/*
+ * Clear inflight log.
+ */
+void clear_inflight(struct thread_data *td)
+{
+ int i;
+
+ if (!td->inflight_numberio)
+ return;
+
+ for (i = 0; i < td->o.iodepth; i++)
+ td->inflight_numberio[i] = INVALID_NUMBERIO;
+
+ td->next_inflight_numberio_idx = 0;
+ /*
+ * Experimental verify can increment io_issues for writes, so catch
+ * inflight_issued up in between loops.
+ */
+ td->inflight_issued = td->io_issues[DDIR_WRITE];
+}
+
/*
* Main IO worker function. It retrieves io_u's to process and queues
* and reaps them, checking for rate and errors along the way.
@@ -1059,6 +1155,7 @@ static void do_io(struct thread_data *td, uint64_t *bytes_done)
io_u_set(td, io_u, IO_U_F_PATTERN_DONE);
io_u->numberio = td->io_issues[io_u->ddir];
populate_verify_io_u(td, io_u);
+ log_inflight(td, io_u);
}
}
@@ -1083,7 +1180,7 @@ static void do_io(struct thread_data *td, uint64_t *bytes_done)
io_u->rand_seed *= __rand(&td->verify_state);
}
- if (verify_state_should_stop(td, io_u)) {
+ if (verify_state_should_stop(td, td->io_issues[io_u->ddir])) {
put_io_u(td, io_u);
break;
}
@@ -1227,49 +1324,29 @@ reap:
bytes_done[i] = td->bytes_done[i] - bytes_done[i];
}
-static void free_file_completion_logging(struct thread_data *td)
+static int init_inflight_logging(struct thread_data *td)
{
- struct fio_file *f;
- unsigned int i;
-
- for_each_file(td, f, i) {
- if (!f->last_write_comp)
- break;
- sfree(f->last_write_comp);
- }
-}
-
-static int init_file_completion_logging(struct thread_data *td,
- unsigned int depth)
-{
- struct fio_file *f;
unsigned int i;
if (td->o.verify == VERIFY_NONE || !td->o.verify_state_save)
return 0;
- /*
- * Async IO completion order may be different from issue order. Double
- * the number of write completions to cover the case the writes issued
- * earlier complete slowly and fall in the last write log entries.
- */
- td->last_write_comp_depth = depth;
- if (!td_ioengine_flagged(td, FIO_SYNCIO))
- td->last_write_comp_depth += depth;
-
- for_each_file(td, f, i) {
- f->last_write_comp = scalloc(td->last_write_comp_depth,
- sizeof(uint64_t));
- if (!f->last_write_comp)
- goto cleanup;
+ td->inflight_numberio = scalloc(td->o.iodepth, sizeof(uint64_t));
+ if (!td->inflight_numberio) {
+ log_err("fio: failed to alloc inflight write data\n");
+ return 1;
}
+ for (i = 0; i < td->o.iodepth; i++)
+ td->inflight_numberio[i] = INVALID_NUMBERIO;
+
return 0;
+}
-cleanup:
- free_file_completion_logging(td);
- log_err("fio: failed to alloc write comp data\n");
- return 1;
+static void free_inflight_logging(struct thread_data *td)
+{
+ if (td->inflight_numberio)
+ sfree(td->inflight_numberio);
}
static void cleanup_io_u(struct thread_data *td)
@@ -1294,16 +1371,15 @@ static void cleanup_io_u(struct thread_data *td)
io_u_qexit(&td->io_u_freelist, false);
io_u_qexit(&td->io_u_all, td_offload_overlap(td));
- free_file_completion_logging(td);
+ free_inflight_logging(td);
}
static int init_io_u(struct thread_data *td)
{
struct io_u *io_u;
- int cl_align, i, max_units;
+ int cl_align, i;
int err;
- max_units = td->o.iodepth;
err = 0;
err += !io_u_rinit(&td->io_u_requeues, td->o.iodepth);
@@ -1317,7 +1393,7 @@ static int init_io_u(struct thread_data *td)
cl_align = os_cache_line_size();
- for (i = 0; i < max_units; i++) {
+ for (i = 0; i < td->o.iodepth; i++) {
void *ptr;
if (td->terminate)
@@ -1334,6 +1410,7 @@ static int init_io_u(struct thread_data *td)
INIT_FLIST_HEAD(&io_u->verify_list);
dprint(FD_MEM, "io_u alloc %p, index %u\n", io_u, i);
+ io_u->inflight_idx = -1;
io_u->index = i;
io_u->flags = IO_U_F_FREE;
io_u_qpush(&td->io_u_freelist, io_u);
@@ -1357,7 +1434,7 @@ static int init_io_u(struct thread_data *td)
if (init_io_u_buffers(td))
return 1;
- if (init_file_completion_logging(td, max_units))
+ if (init_inflight_logging(td))
return 1;
return 0;
diff --git a/file.h b/file.h
index e38ed2f1..8fd40cdf 100644
--- a/file.h
+++ b/file.h
@@ -122,13 +122,6 @@ struct fio_file {
uint64_t first_write;
uint64_t last_write;
- /*
- * Tracks the last iodepth number of completed writes, if data
- * verification is enabled
- */
- uint64_t *last_write_comp;
- unsigned int last_write_idx;
-
/*
* For use by the io engine to store offset
*/
diff --git a/fio.h b/fio.h
index 00f0f09b..e11b9261 100644
--- a/fio.h
+++ b/fio.h
@@ -73,6 +73,8 @@ struct fio_sem;
#define MAX_TRIM_RANGE 256
+#define INVALID_NUMBERIO UINT64_MAX
+
/*
* Range for trim command
*/
@@ -376,6 +378,13 @@ struct thread_data {
uint64_t io_issue_bytes[DDIR_RWDIR_CNT];
uint64_t loops;
+ /*
+ * Keep track of inflight write sequence numbers (numberio) which are used to save verify state.
+ */
+ uint64_t *inflight_numberio;
+ unsigned int next_inflight_numberio_idx;
+ uint64_t inflight_issued;
+
/*
* Completions
*/
@@ -388,7 +397,6 @@ struct thread_data {
struct fio_sem *sem;
uint64_t bytes_done[DDIR_RWDIR_CNT];
uint64_t bytes_verified;
- uint32_t last_write_comp_depth;
uint64_t *thinktime_blocks_counter;
struct timespec last_thinktime;
@@ -782,6 +790,13 @@ extern void lat_target_check(struct thread_data *);
extern void lat_target_init(struct thread_data *);
extern void lat_target_reset(struct thread_data *);
+/*
+ * Inflight log
+ */
+extern void log_inflight(struct thread_data *, struct io_u *);
+extern void invalidate_inflight(struct thread_data *, struct io_u *);
+extern void clear_inflight(struct thread_data *);
+
/*
* Iterates all threads/processes within all the defined jobs
* Usage:
diff --git a/io_u.c b/io_u.c
index ca97f388..6d0f32a8 100644
--- a/io_u.c
+++ b/io_u.c
@@ -2065,8 +2065,6 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u,
static void file_log_write_comp(const struct thread_data *td, struct fio_file *f,
uint64_t offset, unsigned int bytes)
{
- int idx;
-
if (!f)
return;
@@ -2074,14 +2072,6 @@ static void file_log_write_comp(const struct thread_data *td, struct fio_file *f
f->first_write = offset;
if (f->last_write == -1ULL || ((offset + bytes) > f->last_write))
f->last_write = offset + bytes;
-
- if (!f->last_write_comp)
- return;
-
- idx = f->last_write_idx++;
- f->last_write_comp[idx] = offset;
- if (f->last_write_idx == td->last_write_comp_depth)
- f->last_write_idx = 0;
}
static bool should_account(struct thread_data *td)
@@ -2101,6 +2091,7 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr,
assert(io_u->flags & IO_U_F_FLIGHT);
io_u_clear(td, io_u, IO_U_F_FLIGHT | IO_U_F_BUSY_OK | IO_U_F_PATTERN_DONE);
+ invalidate_inflight(td, io_u);
if (td->o.zone_mode == ZONE_MODE_ZBD && td->o.recover_zbd_write_error &&
io_u->error && io_u->ddir == DDIR_WRITE &&
diff --git a/io_u.h b/io_u.h
index 2d20a2b2..68771eba 100644
--- a/io_u.h
+++ b/io_u.h
@@ -46,7 +46,7 @@ struct io_u {
/*
* Write generation
*/
- unsigned short numberio;
+ uint64_t numberio;
/*
* IO priority.
@@ -90,6 +90,8 @@ struct io_u {
unsigned long long resid;
unsigned int error;
+ int inflight_idx;
+
/*
* io engine private data
*/
diff --git a/ioengines.h b/ioengines.h
index bd5d189c..afafeeb9 100644
--- a/ioengines.h
+++ b/ioengines.h
@@ -9,7 +9,7 @@
#include "zbd_types.h"
#include "dataplacement.h"
-#define FIO_IOOPS_VERSION 37
+#define FIO_IOOPS_VERSION 38
#ifndef CONFIG_DYNAMIC_ENGINES
#define FIO_STATIC static
diff --git a/iolog.h b/iolog.h
index e864d169..b52ae87d 100644
--- a/iolog.h
+++ b/iolog.h
@@ -260,7 +260,7 @@ struct io_piece {
struct fio_file *file;
};
unsigned long long offset;
- unsigned short numberio;
+ uint64_t numberio;
unsigned long len;
unsigned int flags;
enum fio_ddir ddir;
diff --git a/libfio.c b/libfio.c
index 2596ae5a..3503c65e 100644
--- a/libfio.c
+++ b/libfio.c
@@ -128,6 +128,8 @@ void clear_io_state(struct thread_data *td, int all)
*/
if (td->o.rand_repeatable)
td_fill_rand_seeds(td);
+
+ clear_inflight(td);
}
void reset_all_stats(struct thread_data *td)
diff --git a/t/verify-state.c b/t/verify-state.c
index f8787e9a..e1b92ee8 100644
--- a/t/verify-state.c
+++ b/t/verify-state.c
@@ -21,19 +21,16 @@ static void show_s(struct thread_io_list *s, unsigned int no_s)
printf("Thread:\t\t%u\n", no_s);
printf("Name:\t\t%s\n", s->name);
- printf("Completions:\t%llu\n", (unsigned long long) s->no_comps);
printf("Depth:\t\t%llu\n", (unsigned long long) s->depth);
- printf("Max completions per file:\t\t%lu\n", (unsigned long) s->max_no_comps_per_file);
printf("Number IOs:\t%llu\n", (unsigned long long) s->numberio);
printf("Index:\t\t%llu\n", (unsigned long long) s->index);
- printf("Completions:\n");
- if (!s->no_comps)
+ printf("Inflight writes:\n");
+ if (!s->depth)
return;
- for (i = s->no_comps - 1; i >= 0; i--) {
- printf("\t(file=%2llu) %llu\n",
- (unsigned long long) s->comps[i].fileno,
- (unsigned long long) s->comps[i].offset);
+ for (i = s->depth - 1; i >= 0; i--) {
+ printf("\t%llu\n",
+ (unsigned long long) s->inflight[i].numberio);
}
}
@@ -45,23 +42,18 @@ static void show(struct thread_io_list *s, size_t size)
do {
int i;
- s->no_comps = le64_to_cpu(s->no_comps);
s->depth = le32_to_cpu(s->depth);
- s->max_no_comps_per_file = le32_to_cpu(s->max_no_comps_per_file);
- s->nofiles = le32_to_cpu(s->nofiles);
s->numberio = le64_to_cpu(s->numberio);
s->index = le64_to_cpu(s->index);
- for (i = 0; i < s->no_comps; i++) {
- s->comps[i].fileno = le64_to_cpu(s->comps[i].fileno);
- s->comps[i].offset = le64_to_cpu(s->comps[i].offset);
- }
+ for (i = 0; i < s->depth; i++)
+ s->inflight[i].numberio = le64_to_cpu(s->inflight[i].numberio);
show_s(s, no_s);
no_s++;
- size -= __thread_io_list_sz(s->max_no_comps_per_file, s->nofiles);
+ size -= __thread_io_list_sz(s->depth);
s = (struct thread_io_list *)((char *) s +
- __thread_io_list_sz(s->max_no_comps_per_file, s->nofiles));
+ __thread_io_list_sz(s->depth));
} while (size != 0);
}
diff --git a/verify-state.h b/verify-state.h
index 603af70d..c055008e 100644
--- a/verify-state.h
+++ b/verify-state.h
@@ -22,24 +22,18 @@ struct thread_rand_state {
};
};
-/*
- * For dumping current write state
- */
-struct file_comp {
- uint64_t fileno;
- uint64_t offset;
+/* a single inflight write */
+struct inflight_write {
+ uint64_t numberio;
};
struct thread_io_list {
- uint64_t no_comps; /* Number of completions saved for the thread */
uint32_t depth; /* I/O depth of the job that saves the verify state */
- uint32_t max_no_comps_per_file;
- uint32_t nofiles;
- uint64_t numberio;
+ uint64_t numberio; /* Number of issued writes */
uint64_t index;
struct thread_rand_state rand;
uint8_t name[64];
- struct file_comp comps[0];
+ struct inflight_write inflight[0];
};
struct all_io_list {
@@ -63,18 +57,18 @@ extern void __verify_save_state(struct all_io_list *, const char *);
extern void verify_save_state(int mask);
extern int verify_load_state(struct thread_data *, const char *);
extern void verify_free_state(struct thread_data *);
-extern int verify_state_should_stop(struct thread_data *, struct io_u *);
+extern int verify_state_should_stop(struct thread_data *, uint64_t);
extern void verify_assign_state(struct thread_data *, void *);
extern int verify_state_hdr(struct verify_state_hdr *, struct thread_io_list *);
-static inline size_t __thread_io_list_sz(uint32_t depth, uint32_t nofiles)
+static inline size_t __thread_io_list_sz(uint32_t depth)
{
- return sizeof(struct thread_io_list) + depth * nofiles * sizeof(struct file_comp);
+ return sizeof(struct thread_io_list) + depth * sizeof(struct inflight_write);
}
static inline size_t thread_io_list_sz(struct thread_io_list *s)
{
- return __thread_io_list_sz(le32_to_cpu(s->max_no_comps_per_file), le32_to_cpu(s->nofiles));
+ return __thread_io_list_sz(le32_to_cpu(s->depth));
}
static inline struct thread_io_list *io_list_next(struct thread_io_list *s)
diff --git a/verify.c b/verify.c
index 04718f30..c7f43c06 100644
--- a/verify.c
+++ b/verify.c
@@ -922,6 +922,11 @@ static int verify_header(struct io_u *io_u, struct thread_data *td,
hdr->magic, FIO_HDR_MAGIC);
goto err;
}
+ if (hdr->version != VERIFY_HEADER_VERSION) {
+ log_err("verify: unsupported header version %x, wanted %x. Are you trying to verify across versions of fio?",
+ hdr->version, VERIFY_HEADER_VERSION);
+ goto err;
+ }
if (hdr->len != hdr_len) {
log_err("verify: bad header length %u, wanted %u",
hdr->len, hdr_len);
@@ -951,8 +956,8 @@ static int verify_header(struct io_u *io_u, struct thread_data *td,
!td->o.time_based)
if (td->o.verify_write_sequence)
if (hdr->numberio != io_u->numberio) {
- log_err("verify: bad header numberio %"PRIu16
- ", wanted %"PRIu16,
+ log_err("verify: bad header numberio %"PRIu64
+ ", wanted %"PRIu64,
hdr->numberio, io_u->numberio);
goto err;
}
@@ -1260,6 +1265,7 @@ static void __fill_hdr(struct thread_data *td, struct io_u *io_u,
void *p = hdr;
hdr->magic = FIO_HDR_MAGIC;
+ hdr->version = VERIFY_HEADER_VERSION;
hdr->verify_type = td->o.verify;
hdr->len = header_len;
hdr->rand_seed = rand_seed;
@@ -1629,47 +1635,6 @@ int paste_blockoff(char *buf, unsigned int len, void *priv)
return 0;
}
-static int __fill_file_completions(struct thread_data *td,
- struct thread_io_list *s,
- struct fio_file *f, unsigned int *index)
-{
- unsigned int comps;
- int i, j;
-
- if (!f->last_write_comp)
- return 0;
-
- if (td->io_blocks[DDIR_WRITE] < td->last_write_comp_depth)
- comps = td->io_blocks[DDIR_WRITE];
- else
- comps = td->last_write_comp_depth;
-
- j = f->last_write_idx - 1;
- for (i = 0; i < comps; i++) {
- if (j == -1)
- j = td->last_write_comp_depth - 1;
- s->comps[*index].fileno = __cpu_to_le64(f->fileno);
- s->comps[*index].offset = cpu_to_le64(f->last_write_comp[j]);
- (*index)++;
- j--;
- }
-
- return comps;
-}
-
-static int fill_file_completions(struct thread_data *td,
- struct thread_io_list *s, unsigned int *index)
-{
- struct fio_file *f;
- unsigned int i;
- int comps = 0;
-
- for_each_file(td, f, i)
- comps += __fill_file_completions(td, s, f, index);
-
- return comps;
-}
-
struct all_io_list *get_all_io_list(int save_mask, size_t *sz)
{
struct all_io_list *rep;
@@ -1690,7 +1655,7 @@ struct all_io_list *get_all_io_list(int save_mask, size_t *sz)
continue;
td->stop_io = 1;
td->flags |= TD_F_VSTATE_SAVED;
- depth += (td->last_write_comp_depth * td->o.nr_files);
+ depth += (td->o.iodepth * td->o.nr_files);
nr++;
} end_for_each();
@@ -1699,7 +1664,7 @@ struct all_io_list *get_all_io_list(int save_mask, size_t *sz)
*sz = sizeof(*rep);
*sz += nr * sizeof(struct thread_io_list);
- *sz += depth * sizeof(struct file_comp);
+ *sz += depth * sizeof(struct inflight_write);
rep = calloc(1, *sz);
rep->threads = cpu_to_le64((uint64_t) nr);
@@ -1707,18 +1672,15 @@ struct all_io_list *get_all_io_list(int save_mask, size_t *sz)
next = &rep->state[0];
for_each_td(td) {
struct thread_io_list *s = next;
- unsigned int comps, index = 0;
if (save_mask != IO_LIST_ALL && (__td_index + 1) != save_mask)
continue;
- comps = fill_file_completions(td, s, &index);
+ for (int i = 0; i < td->o.iodepth; i++)
+ s->inflight[i].numberio = cpu_to_le64(atomic_load_acquire(&td->inflight_numberio[i]));
- s->no_comps = cpu_to_le64((uint64_t) comps);
s->depth = cpu_to_le32((uint32_t) td->o.iodepth);
- s->max_no_comps_per_file = cpu_to_le32((uint32_t) td->last_write_comp_depth);
- s->nofiles = cpu_to_le32((uint32_t) td->o.nr_files);
- s->numberio = cpu_to_le64((uint64_t) td->io_issues[DDIR_WRITE]);
+ s->numberio = cpu_to_le64((uint64_t) atomic_load_acquire(&td->inflight_issued));
s->index = cpu_to_le64((uint64_t) __td_index);
if (td->random_state.use64) {
s->rand.state64.s[0] = cpu_to_le64(td->random_state.state64.s1);
@@ -1846,10 +1808,7 @@ void verify_assign_state(struct thread_data *td, void *p)
struct thread_io_list *s = p;
int i;
- s->no_comps = le64_to_cpu(s->no_comps);
s->depth = le32_to_cpu(s->depth);
- s->max_no_comps_per_file = le32_to_cpu(s->max_no_comps_per_file);
- s->nofiles = le32_to_cpu(s->nofiles);
s->numberio = le64_to_cpu(s->numberio);
s->rand.use64 = le64_to_cpu(s->rand.use64);
@@ -1861,9 +1820,9 @@ void verify_assign_state(struct thread_data *td, void *p)
s->rand.state32.s[i] = le32_to_cpu(s->rand.state32.s[i]);
}
- for (i = 0; i < s->no_comps; i++) {
- s->comps[i].fileno = le64_to_cpu(s->comps[i].fileno);
- s->comps[i].offset = le64_to_cpu(s->comps[i].offset);
+ for (i = 0; i < s->depth; i++) {
+ s->inflight[i].numberio = le64_to_cpu(s->inflight[i].numberio);
+ dprint(FD_VERIFY, "verify_assign_state numberio=%"PRIu64", inflight[%d]=%"PRIu64"\n", s->numberio, i, s->inflight[i].numberio);
}
td->vstate = p;
@@ -1949,40 +1908,31 @@ err:
/*
* Use the loaded verify state to know when to stop doing verification
*/
-int verify_state_should_stop(struct thread_data *td, struct io_u *io_u)
+int verify_state_should_stop(struct thread_data *td, uint64_t numberio)
{
struct thread_io_list *s = td->vstate;
- struct fio_file *f = io_u->file;
int i;
- if (!s || !f)
+ dprint(FD_VERIFY, "verify_state_should_stop numberio=%"PRIu64"\n", numberio);
+ if (!s)
return 0;
- /*
- * If we're not into the window of issues - depth yet, continue. If
- * issue is shorter than depth, do check.
- */
- if ((td->io_blocks[DDIR_READ] < s->depth ||
- s->numberio - td->io_blocks[DDIR_READ] > s->depth) &&
- s->numberio > s->depth)
- return 0;
-
- /*
- * We're in the window of having to check if this io was
- * completed or not. If the IO was seen as completed, then
- * lets verify it.
+ /* If the current seq is lower than the max issued seq, check to make sure
+ * the write was not inflight.
*/
- for (i = 0; i < s->no_comps; i++) {
- if (s->comps[i].fileno != f->fileno)
- continue;
- if (io_u->verify_offset == s->comps[i].offset)
- return 0;
+ if (numberio < s->numberio) {
+ for (i = 0; i < s->depth; i++) {
+ if (s->inflight[i].numberio == numberio) {
+ log_info("Stop verify because seq %"PRIu64" was an inflight write\n",
+ numberio);
+ return 1;
+ }
+ }
+ } else {
+ log_info("Stop verify because seq %"PRIu64" >= %"PRIu64"\n",
+ numberio, s->numberio);
+ return 1;
}
- /*
- * Not found, we have to stop
- */
- log_info("Stop verify because offset %llu in %s is not recorded in verify state\n",
- io_u->verify_offset, f->file_name);
- return 1;
+ return 0;
}
diff --git a/verify.h b/verify.h
index 539e6f6c..e361337c 100644
--- a/verify.h
+++ b/verify.h
@@ -32,6 +32,12 @@ enum {
VERIFY_NULL, /* pretend to verify */
};
+/*
+ * Set the high bit to distinguish versioned headers from older
+ * non-versioned headers.
+ */
+#define VERIFY_HEADER_VERSION 0x81
+
/*
* A header structure associated with each checksummed data block. It is
* followed by a checksum specific header that contains the verification
@@ -39,14 +45,15 @@ enum {
*/
struct verify_header {
uint16_t magic;
- uint16_t verify_type;
+ uint8_t version;
+ uint8_t verify_type;
uint32_t len;
uint64_t rand_seed;
uint64_t offset;
uint32_t time_sec;
uint32_t time_nsec;
+ uint64_t numberio;
uint16_t thread;
- uint16_t numberio;
uint32_t crc32;
};