The following changes since commit 479471c409a61d01290ac9444042357b03f8d0b0:

  server: make the connect code fully IPv6 (2014-01-23 20:42:06 -0800)

are available in the git repository at:
  git://git.kernel.dk/fio.git master

Jens Axboe (2):
      engine: more checks on IPv6 and multicast
      Add verify_only to man page

Juan Casse (3):
      Adds check for numberio during verify phase.
      Adds verify_only option
      Adds check for rand_seed during verify phase.

 HOWTO            |   11 ++++++++-
 backend.c        |   43 ++++++++++++++++++++++++++++++++++++-
 engines/net.c    |    8 ++++++-
 fio.1            |    7 ++++++
 ioengine.h       |    1 +
 iolog.c          |    1 +
 iolog.h          |    1 +
 libfio.c         |    1 -
 options.c        |    9 +++++++
 thread_options.h |    2 +
 verify.c         |   63 +++++++++++++++++++++++++++++++++++++++++++++--------
 11 files changed, 133 insertions(+), 14 deletions(-)

---

Diff of recent changes:

diff --git a/HOWTO b/HOWTO
index e69cf41..9830fa1 100644
--- a/HOWTO
+++ b/HOWTO
@@ -1068,6 +1068,13 @@ loops=int        Run the specified number of iterations 
of this job. Used
                to repeat the same workload a given number of times. Defaults
                to 1.
 
+verify_only    Do not perform specified workload---only verify data still
+               matches previous invocation of this workload. This option
+               allows one to check data multiple times at a later date
+               without overwriting it. This option makes sense only for
+               workloads that write data, and does not support workloads
+               with the time_based option set.
+
 do_verify=bool Run the verify phase after a write phase. Only makes sense if
                verify is set. Defaults to 1.
 
@@ -1106,7 +1113,9 @@ verify=str        If writing to a file, fio can verify 
the file contents
 
                        meta    Write extra information about each io
                                (timestamp, block number etc.). The block
-                               number is verified. See also verify_pattern.
+                               number is verified. The io sequence number is
+                               verified for workloads that write data.
+                               See also verify_pattern.
 
                        null    Only pretend to verify. Useful for testing
                                internals with ioengine=null, not for much
diff --git a/backend.c b/backend.c
index c9a20a3..93e6632 100644
--- a/backend.c
+++ b/backend.c
@@ -1120,6 +1120,44 @@ static int exec_string(struct thread_options *o, const 
char *string, const char
 }
 
 /*
+ * Dry run to compute correct state of numberio for verification.
+ */
+static uint64_t do_dry_run(struct thread_data *td)
+{
+       uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
+
+       td_set_runstate(td, TD_RUNNING);
+
+       while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
+               (!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td)) {
+               struct io_u *io_u;
+               int ret;
+
+               if (td->terminate || td->done)
+                       break;
+
+               io_u = get_io_u(td);
+               if (!io_u)
+                       break;
+
+               io_u->flags |= IO_U_F_FLIGHT;
+               io_u->error = 0;
+               io_u->resid = 0;
+               if (ddir_rw(acct_ddir(io_u)))
+                       td->io_issues[acct_ddir(io_u)]++;
+               if (ddir_rw(io_u->ddir)) {
+                       io_u_mark_depth(td, 1);
+                       td->ts.total_io_u[io_u->ddir]++;
+               }
+
+               ret = io_u_sync_complete(td, io_u, bytes_done);
+               (void) ret;
+       }
+
+       return bytes_done[DDIR_WRITE] + bytes_done[DDIR_TRIM];
+}
+
+/*
  * Entry point for the thread based jobs. The process based jobs end up
  * here as well, after a little setup.
  */
@@ -1332,7 +1370,10 @@ static void *thread_main(void *data)
 
                prune_io_piece_log(td);
 
-               verify_bytes = do_io(td);
+               if (td->o.verify_only && (td_write(td) || td_rw(td)))
+                       verify_bytes = do_dry_run(td);
+               else
+                       verify_bytes = do_io(td);
 
                clear_state = 1;
 
diff --git a/engines/net.c b/engines/net.c
index 5fdc88c..4be106a 100644
--- a/engines/net.c
+++ b/engines/net.c
@@ -1039,12 +1039,17 @@ static int fio_netio_setup_listen_inet(struct 
thread_data *td, short port)
        }
 #endif
 
-       if (td->o.filename){
+       if (td->o.filename) {
                if (!is_udp(o) || !fio_netio_is_multicast(td->o.filename)) {
                        log_err("fio: hostname not valid for non-multicast 
inbound network IO\n");
                        close(fd);
                        return 1;
                }
+               if (is_ipv6(o)) {
+                       log_err("fio: IPv6 not supported for multicast network 
IO");
+                       close(fd);
+                       return 1;
+               }
 
                inet_aton(td->o.filename, &sin.sin_addr);
 
@@ -1058,6 +1063,7 @@ static int fio_netio_setup_listen_inet(struct thread_data 
*td, short port)
                } else {
                        mr.imr_interface.s_addr = htonl(INADDR_ANY);
                }
+
                if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const 
char*)&mr, sizeof(mr)) < 0) {
                        td_verror(td, errno, "setsockopt IP_ADD_MEMBERSHIP");
                        close(fd);
diff --git a/fio.1 b/fio.1
index b5ff80c..3cdfd27 100644
--- a/fio.1
+++ b/fio.1
@@ -934,6 +934,13 @@ Unlink job files when done.  Default: false.
 Specifies the number of iterations (runs of the same workload) of this job.
 Default: 1.
 .TP
+.BI verify_only \fR=\fPbool
+Do not perform the specified workload, only verify data still matches previous
+invocation of this workload. This option allows one to check data multiple
+times at a later date without overwriting it. This option makes sense only for
+workloads that write data, and does not support workloads with the
+\fBtime_based\fR option set.
+.TP
 .BI do_verify \fR=\fPbool
 Run the verify phase after a write phase.  Only valid if \fBverify\fR is set.
 Default: true.
diff --git a/ioengine.h b/ioengine.h
index 6dd2aa4..949af91 100644
--- a/ioengine.h
+++ b/ioengine.h
@@ -50,6 +50,7 @@ struct io_u {
         */
        unsigned long buflen;
        unsigned long long offset;
+       unsigned short numberio;
        void *buf;
 
        /*
diff --git a/iolog.c b/iolog.c
index 6593367..ec29971 100644
--- a/iolog.c
+++ b/iolog.c
@@ -188,6 +188,7 @@ void log_io_piece(struct thread_data *td, struct io_u *io_u)
        ipo->file = io_u->file;
        ipo->offset = io_u->offset;
        ipo->len = io_u->buflen;
+       ipo->numberio = io_u->numberio;
 
        if (io_u_should_trim(td, io_u)) {
                flist_add_tail(&ipo->trim_list, &td->trim_list);
diff --git a/iolog.h b/iolog.h
index 6503acf..321576d 100644
--- a/iolog.h
+++ b/iolog.h
@@ -83,6 +83,7 @@ struct io_piece {
                struct fio_file *file;
        };
        unsigned long long offset;
+       unsigned short numberio;
        unsigned long len;
        unsigned int flags;
        enum fio_ddir ddir;
diff --git a/libfio.c b/libfio.c
index 7eb4576..222cd16 100644
--- a/libfio.c
+++ b/libfio.c
@@ -85,7 +85,6 @@ static void reset_io_counters(struct thread_data *td)
                td->this_io_blocks[ddir] = 0;
                td->rate_bytes[ddir] = 0;
                td->rate_blocks[ddir] = 0;
-               td->io_issues[ddir] = 0;
        }
        td->zone_bytes = 0;
 
diff --git a/options.c b/options.c
index b1b6c8e..525d318 100644
--- a/options.c
+++ b/options.c
@@ -2018,6 +2018,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .group  = FIO_OPT_G_RUNTIME,
        },
        {
+               .name   = "verify_only",
+               .lname  = "Verify only",
+               .type   = FIO_OPT_STR_SET,
+               .off1   = td_var_offset(verify_only),
+               .help   = "Verifies previously written data is still valid",
+               .category = FIO_OPT_C_GENERAL,
+               .group  = FIO_OPT_G_RUNTIME,
+       },
+       {
                .name   = "ramp_time",
                .lname  = "Ramp time",
                .type   = FIO_OPT_STR_VAL_TIME,
diff --git a/thread_options.h b/thread_options.h
index f40a992..2f807cd 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -109,6 +109,8 @@ struct thread_options {
        unsigned int fsync_on_close;
        unsigned int bs_is_seq_rand;
 
+       unsigned int verify_only;
+
        unsigned int random_distribution;
 
        fio_fp64_t zipf_theta;
diff --git a/verify.c b/verify.c
index 721aeb4..568bae8 100644
--- a/verify.c
+++ b/verify.c
@@ -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,41 @@ 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)) {
+               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 +822,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 +996,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 +1030,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;
 
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to