Fix rand_seed mismatches in verify phase
[fio.git] / verify.c
index 721aeb46635701b3f0f1cca8fc2db18d8c2cc4eb..90cd093add1fbbb13ba2f9d713ce60dc9e4f49e9 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -72,10 +72,10 @@ void fill_verify_pattern(struct thread_data *td, void *p, unsigned int len,
                if (use_seed)
                        __fill_random_buf(p, len, seed);
                else
-                       io_u->rand_seed = fill_random_buf(&td->buf_state, p, len);
+                       io_u->rand_seed = fill_random_buf(&td->__verify_state, p, len);
                return;
        }
-       
+
        if (io_u->buf_filled_len >= len) {
                dprint(FD_VERIFY, "using already filled verify pattern b=%d len=%u\n",
                        td->o.verify_pattern_bytes, len);
@@ -383,6 +383,19 @@ static int verify_io_u_meta(struct verify_header *hdr, struct vcont *vc)
        if (td->o.verify_pattern_bytes)
                ret |= verify_io_u_pattern(hdr, vc);
 
+       /*
+        * For read-only workloads, the program cannot be certain of the
+        * last numberio written to a block. Checking of numberio will be done
+        * only for workloads that write data.
+        * For verify_only, numberio will be checked in the last iteration when
+        * the correct state of numberio, that would have been written to each
+        * block in a previous run of fio, has been reached.
+        */
+       if (td_write(td) || td_rw(td))
+               if (!td->o.verify_only || td->o.loops == 0)
+                       if (vh->numberio != io_u->numberio)
+                               ret = EILSEQ;
+
        if (!ret)
                return 0;
 
@@ -658,18 +671,17 @@ static int verify_header(struct io_u *io_u, struct verify_header *hdr)
        uint32_t crc;
 
        if (hdr->magic != FIO_HDR_MAGIC)
-               return 0;
-       if (hdr->len > io_u->buflen) {
-               log_err("fio: verify header exceeds buffer length (%u > %lu)\n", hdr->len, io_u->buflen);
-               return 0;
-       }
+               return 1;
+       if (hdr->len > io_u->buflen)
+               return 2;
+       if (hdr->rand_seed != io_u->rand_seed)
+               return 3;
 
        crc = fio_crc32c(p, offsetof(struct verify_header, crc32));
        if (crc == hdr->crc32)
-               return 1;
-
+               return 0;
        log_err("fio: verify header crc %x, calculated %x\n", hdr->crc32, crc);
-       return 0;
+       return 4;
 }
 
 int verify_io_u(struct thread_data *td, struct io_u *io_u)
@@ -706,13 +718,48 @@ int verify_io_u(struct thread_data *td, struct io_u *io_u)
                        memswp(p, p + td->o.verify_offset, header_size);
                hdr = p;
 
-               if (!verify_header(io_u, hdr)) {
+               /*
+                * Make rand_seed check pass when have verifysort or
+                * verify_backlog.
+                */
+               if (td->o.verifysort || (td->flags & TD_F_VER_BACKLOG))
+                       io_u->rand_seed = hdr->rand_seed;
+
+               ret = verify_header(io_u, hdr);
+               switch (ret) {
+               case 0:
+                       break;
+               case 1:
                        log_err("verify: bad magic header %x, wanted %x at "
                                "file %s offset %llu, length %u\n",
                                hdr->magic, FIO_HDR_MAGIC,
                                io_u->file->file_name,
                                io_u->offset + hdr_num * hdr->len, hdr->len);
                        return EILSEQ;
+                       break;
+               case 2:
+                       log_err("fio: verify header exceeds buffer length (%u "
+                               "> %lu)\n", hdr->len, io_u->buflen);
+                       return EILSEQ;
+                       break;
+               case 3:
+                       log_err("verify: bad header rand_seed %"PRIu64
+                               ", wanted %"PRIu64" at file %s offset %llu, "
+                               "length %u\n",
+                               hdr->rand_seed, io_u->rand_seed,
+                               io_u->file->file_name,
+                               io_u->offset + hdr_num * hdr->len, hdr->len);
+                       return EILSEQ;
+                       break;
+               case 4:
+                       return EILSEQ;
+                       break;
+               default:
+                       log_err("verify: unknown header error at file %s "
+                       "offset %llu, length %u\n",
+                       io_u->file->file_name,
+                       io_u->offset + hdr_num * hdr->len, hdr->len);
+                       return EILSEQ;
                }
 
                if (td->o.verify != VERIFY_NONE)
@@ -782,7 +829,7 @@ static void fill_meta(struct verify_header *hdr, struct thread_data *td,
        vh->time_sec = io_u->start_time.tv_sec;
        vh->time_usec = io_u->start_time.tv_usec;
 
-       vh->numberio = td->io_issues[DDIR_WRITE];
+       vh->numberio = io_u->numberio;
 
        vh->offset = io_u->offset + header_num * td->o.verify_interval;
 }
@@ -956,6 +1003,8 @@ void populate_verify_io_u(struct thread_data *td, struct io_u *io_u)
        if (td->o.verify == VERIFY_NULL)
                return;
 
+       io_u->numberio = td->io_issues[io_u->ddir];
+
        fill_pattern_headers(td, io_u, 0, 0);
 }
 
@@ -988,6 +1037,7 @@ int get_next_verify(struct thread_data *td, struct io_u *io_u)
 
                io_u->offset = ipo->offset;
                io_u->buflen = ipo->len;
+               io_u->numberio = ipo->numberio;
                io_u->file = ipo->file;
                io_u->flags |= IO_U_F_VER_LIST;
 
@@ -1013,6 +1063,12 @@ int get_next_verify(struct thread_data *td, struct io_u *io_u)
                remove_trim_entry(td, ipo);
                free(ipo);
                dprint(FD_VERIFY, "get_next_verify: ret io_u %p\n", io_u);
+
+               if (!td->o.verify_pattern_bytes) {
+                       io_u->rand_seed = __rand(&td->__verify_state);
+                       if (sizeof(int) != sizeof(long *))
+                               io_u->rand_seed *= __rand(&td->__verify_state);
+               }
                return 0;
        }