Bad header rand_seed with time_based or loops with randrepeat=0 verify
authorHorshack <horshack@live.com>
Sat, 18 Feb 2023 20:22:54 +0000 (15:22 -0500)
committerHorshack <horshack@live.com>
Sat, 18 Feb 2023 21:02:44 +0000 (16:02 -0500)
Verify fails with "bad header rand_seed" when multiple iterations of
do_io() execute (time_based=1 or loops>0), with verify enabled
and randrepeat=0

The root cause is do_verify() resetting the verify seed back to the
job-init value, which works for verification of the first iteration of
do_io() but fails for subsequent iterations because the seed is left in
its post-do_io() state after the first do_verify(), which means
different rand values for the second iteration of do_io() yet the second
iteration of do_verify() will revert back again to the job-init seed
value.

The fix is to revert the verify seed for randrepeat=0 back to ts state
when do_io() last ran rather than to its job-init value. That will allow
do_verify() to use the correct seed for each iteration while still
retaining a per-iteration unique verify seed.

Link: https://github.com/axboe/fio/issues/1517#issuecomment-1430282533
Signed-off-by: Adam Horshack (horshack@live.com)
backend.c
fio.h

index 0ccc7c2b72aaaf9c1924ea63824e74f911e4c02c..9ea688fb1f0ca9e7e67cc10479df6d3b9f68e25a 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -637,15 +637,6 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
        if (td->error)
                return;
 
-       /*
-        * verify_state needs to be reset before verification
-        * proceeds so that expected random seeds match actual
-        * random seeds in headers. The main loop will reset
-        * all random number generators if randrepeat is set.
-        */
-       if (!td->o.rand_repeatable)
-               td_fill_verify_state_seed(td);
-
        td_set_runstate(td, TD_VERIFYING);
 
        io_u = NULL;
@@ -1878,8 +1869,12 @@ static void *thread_main(void *data)
                if (td->o.verify_only && td_write(td))
                        verify_bytes = do_dry_run(td);
                else {
+                       if (!td->o.rand_repeatable)
+                               /* save verify rand state to replay hdr seeds later at verify */
+                               frand_copy(&td->verify_state_last_do_io, &td->verify_state);
                        do_io(td, bytes_done);
-
+                       if (!td->o.rand_repeatable)
+                               frand_copy(&td->verify_state, &td->verify_state_last_do_io);
                        if (!ddir_rw_sum(bytes_done)) {
                                fio_mark_td_terminate(td);
                                verify_bytes = 0;
diff --git a/fio.h b/fio.h
index 8da776403e1d1abb1f5482d69a9c61918dbfa635..09c441491be9a41221042d6d837038adb55d0100 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -258,6 +258,7 @@ struct thread_data {
 
        struct frand_state bsrange_state[DDIR_RWDIR_CNT];
        struct frand_state verify_state;
+       struct frand_state verify_state_last_do_io;
        struct frand_state trim_state;
        struct frand_state delay_state;