Fix verify
[fio.git] / verify.c
index 3eac9cab4ebaa975c7e20f4e57aade6bbc1738f9..0a504deb15f2e22ca6ce20a526296cd97102fcb4 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -36,41 +36,27 @@ void fill_pattern(struct thread_data *td, void *p, unsigned int len, struct io_u
                if (use_seed)
                        __fill_random_buf(p, len, seed);
                else
-                       io_u->rand_seed = fill_random_buf(p, len);
+                       io_u->rand_seed = fill_random_buf(&td->buf_state, p, len);
                break;
        case 1:
-               /*
-                * See below write barrier comment
-                */
-#if 0
-               read_barrier();
                if (io_u->buf_filled_len >= len) {
                        dprint(FD_VERIFY, "using already filled verify pattern b=0 len=%u\n", len);
                        return;
                }
-#endif
                dprint(FD_VERIFY, "fill verify pattern b=0 len=%u\n", len);
                memset(p, td->o.verify_pattern[0], len);
-               /*
-                * We need to ensure that the pattern stores are seen before
-                * the fill length store, or we could observe headers that
-                * aren't valid to the extent notified by the fill length
-                */
-               write_barrier();
                io_u->buf_filled_len = len;
                break;
        default: {
                unsigned int i = 0, size = 0;
                unsigned char *b = p;
 
-#if 0
-               read_barrier();
                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);
                        return;
                }
-#endif
+
                dprint(FD_VERIFY, "fill verify pattern b=%d len=%u\n",
                                        td->o.verify_pattern_bytes, len);
 
@@ -81,7 +67,6 @@ void fill_pattern(struct thread_data *td, void *p, unsigned int len, struct io_u
                        memcpy(b+i, td->o.verify_pattern, size);
                        i += size;
                }
-               write_barrier();
                io_u->buf_filled_len = len;
                break;
                }
@@ -269,6 +254,9 @@ static void dump_verify_buffers(struct verify_header *hdr, struct vcont *vc)
        struct io_u dummy;
        void *buf;
 
+       if (!td->o.verify_dump)
+               return;
+
        /*
         * Dump the contents we just read off disk
         */
@@ -333,15 +321,28 @@ static int verify_io_u_pattern(struct verify_header *hdr, struct vcont *vc)
        struct thread_data *td = vc->td;
        struct io_u *io_u = vc->io_u;
        char *buf, *pattern;
-       unsigned int hdr_size = __hdr_size(td->o.verify);
-       unsigned int len, mod, i;
+       unsigned int header_size = __hdr_size(td->o.verify);
+       unsigned int len, mod, i, size, pattern_size;
 
        pattern = td->o.verify_pattern;
-       buf = (void *) hdr + hdr_size;
-       len = get_hdr_inc(td, io_u) - hdr_size;
-       mod = hdr_size % td->o.verify_pattern_bytes;
+       pattern_size = td->o.verify_pattern_bytes;
+       if (pattern_size <= 1)
+               pattern_size = MAX_PATTERN_SIZE;
+       buf = (void *) hdr + header_size;
+       len = get_hdr_inc(td, io_u) - header_size;
+       mod = header_size % pattern_size;
+
+       for (i = 0; i < len; i += size) {
+               size = pattern_size - mod;
+               if (size > (len - i))
+                       size = len - i;
+               if (memcmp(buf + i, pattern + mod, size))
+                       /* Let the slow compare find the first mismatch byte. */
+                       break;
+               mod = 0;
+       }
 
-       for (i = 0; i < len; i++) {
+       for (; i < len; i++) {
                if (buf[i] != pattern[mod]) {
                        unsigned int bits;
 
@@ -550,10 +551,7 @@ static int verify_io_u_crc32c(struct verify_header *hdr, struct vcont *vc)
 
        dprint(FD_VERIFY, "crc32c verify io_u %p, len %u\n", vc->io_u, hdr->len);
 
-       if (hdr->verify_type == VERIFY_CRC32C_INTEL)
-               c = crc32c_intel(p, hdr->len - hdr_size(hdr));
-       else
-               c = crc32c(p, hdr->len - hdr_size(hdr));
+       c = crc32c(p, hdr->len - hdr_size(hdr));
 
        if (c == vh->crc32)
                return 0;
@@ -599,10 +597,8 @@ int verify_io_u_async(struct thread_data *td, struct io_u *io_u)
        if (io_u->file)
                put_file_log(td, io_u->file);
 
-       io_u->file = NULL;
-
        pthread_mutex_lock(&td->io_u_lock);
-       
+
        if (io_u->flags & IO_U_F_IN_CUR_DEPTH) {
                td->cur_depth--;
                io_u->flags &= ~IO_U_F_IN_CUR_DEPTH;
@@ -650,10 +646,26 @@ static int verify_trimmed_io_u(struct thread_data *td, struct io_u *io_u)
        return ret;
 }
 
+static int verify_header(struct verify_header *hdr)
+{
+       void *p = hdr;
+       uint32_t crc;
+
+       if (hdr->magic != FIO_HDR_MAGIC)
+               return 0;
+
+       crc = crc32c(p, offsetof(struct verify_header, crc32));
+       if (crc == hdr->crc32)
+               return 1;
+
+       log_err("fio: verify header crc %x, calculated %x\n", hdr->crc32, crc);
+       return 0;
+}
+
 int verify_io_u(struct thread_data *td, struct io_u *io_u)
 {
        struct verify_header *hdr;
-       unsigned int hdr_size, hdr_inc, hdr_num = 0;
+       unsigned int header_size, hdr_inc, hdr_num = 0;
        void *p;
        int ret;
 
@@ -678,14 +690,15 @@ int verify_io_u(struct thread_data *td, struct io_u *io_u)
                if (ret && td->o.verify_fatal)
                        break;
 
-               hdr_size = __hdr_size(td->o.verify);
+               header_size = __hdr_size(td->o.verify);
                if (td->o.verify_offset)
-                       memswp(p, p + td->o.verify_offset, hdr_size);
+                       memswp(p, p + td->o.verify_offset, header_size);
                hdr = p;
 
-               if (hdr->fio_magic != FIO_HDR_MAGIC) {
-                       log_err("verify: bad magic header %x, wanted %x at file %s offset %llu, length %u\n",
-                               hdr->fio_magic, FIO_HDR_MAGIC,
+               if (!verify_header(hdr)) {
+                       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;
@@ -812,10 +825,7 @@ static void fill_crc32c(struct verify_header *hdr, void *p, unsigned int len)
 {
        struct vhdr_crc32 *vh = hdr_priv(hdr);
 
-       if (hdr->verify_type == VERIFY_CRC32C_INTEL)
-               vh->crc32 = crc32c_intel(p, len);
-       else
-               vh->crc32 = crc32c(p, len);
+       vh->crc32 = crc32c(p, len);
 }
 
 static void fill_crc64(struct verify_header *hdr, void *p, unsigned int len)
@@ -845,10 +855,12 @@ static void populate_hdr(struct thread_data *td, struct io_u *io_u,
 
        p = (void *) hdr;
 
-       hdr->fio_magic = FIO_HDR_MAGIC;
-       hdr->len = header_len;
+       hdr->magic = FIO_HDR_MAGIC;
        hdr->verify_type = td->o.verify;
+       hdr->len = header_len;
        hdr->rand_seed = io_u->rand_seed;
+       hdr->crc32 = crc32c(p, offsetof(struct verify_header, crc32));
+
        data_len = header_len - hdr_size(hdr);
 
        data = p + hdr_size(hdr);
@@ -1032,7 +1044,7 @@ static void *verify_async_thread(void *data)
                        put_io_u(td, io_u);
                        if (!ret)
                                continue;
-                       if (td->o.continue_on_error &&
+                       if (td->o.continue_on_error & ERROR_TYPE_VERIFY &&
                            td_non_fatal_error(ret)) {
                                update_error_count(td, ret);
                                td_clear_error(td);