Adds verify_only option
authorJuan Casse <jcasse@chromium.org>
Tue, 17 Sep 2013 21:06:13 +0000 (14:06 -0700)
committerJens Axboe <axboe@kernel.dk>
Fri, 24 Jan 2014 20:05:45 +0000 (12:05 -0800)
When this option is set, a dry run (no actual io is performed) of the
workload will be done in order to compute the numberio for each block
header without overwriting the data on disk. Then, do_verify() will be
effectively verifying data that was written in a previous fio run.
In the case that "loops" is set to more than 1, do_verify() will delay
the verification of numberio to the last iteration when the same
numberio state that would have been written to disk in a previous
fio run has been reached.

Signed-off-by: Juan Casse <jcasse@chromium.org>
Reviewed-by: Grant Grundler <grundler@chromium.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
HOWTO
backend.c
options.c
thread_options.h
verify.c

diff --git a/HOWTO b/HOWTO
index e69cf4130696c55bf0af6cc3f224d6136af5666b..9830fa1ebd9510f693c3978c70c5c9121d7eabdd 100644 (file)
--- 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
index c9a20a3b36a188e01df2b5865f8e68140b28028f..93e66325f08569ec23fee63eb020065191d30616 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -1119,6 +1119,44 @@ static int exec_string(struct thread_options *o, const char *string, const char
        return ret;
 }
 
+/*
+ * 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;
 
index b1b6c8e969381cc44cdde496fbcb4ad174c84a84..525d31840c5e7f55944f2acec3210973de581057 100644 (file)
--- a/options.c
+++ b/options.c
@@ -2017,6 +2017,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_GENERAL,
                .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",
index f40a9927e58e982098695ebb946608e38e0e3407..2f807cd788b1ac154e67df4840efe71a5e72087a 100644 (file)
@@ -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;
index f592c55c509e6e811417bf73b654b9dfae8adce5..371b650a50a327f383672fb41bb332adaa3e7bde 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -387,10 +387,14 @@ static int verify_io_u_meta(struct verify_header *hdr, struct vcont *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 (vh->numberio != io_u->numberio)
-                       ret = EILSEQ;
+               if (!td->o.verify_only || td->o.loops == 0)
+                       if (vh->numberio != io_u->numberio)
+                               ret = EILSEQ;
 
        if (!ret)
                return 0;