verify: add new experimental mode that requires no meta data
authorJens Axboe <axboe@kernel.dk>
Mon, 21 Jan 2013 16:47:03 +0000 (09:47 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 21 Jan 2013 16:47:03 +0000 (09:47 -0700)
Should work fine, but we need to account and track trims to know
which blocks NOT to verify (or verify as zero).

Signed-off-by: Jens Axboe <axboe@kernel.dk>
backend.c
fio.h
io_u.c
libfio.c

index 7cebf4d30cbeabe7b32adca54fd0561a29f3a634..507faa9992e7325d4c80de368e43f2a779893739 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -393,11 +393,12 @@ static int break_on_this_error(struct thread_data *td, enum fio_ddir ddir,
  * The main verify engine. Runs over the writes we previously submitted,
  * reads the blocks back in, and checks the crc/md5 of the data.
  */
-static void do_verify(struct thread_data *td)
+static void do_verify(struct thread_data *td, uint64_t verify_bytes)
 {
        struct fio_file *f;
        struct io_u *io_u;
        int ret, min_events;
+       uint64_t io_bytes;
        unsigned int i;
 
        dprint(FD_VERIFY, "starting loop\n");
@@ -421,6 +422,7 @@ static void do_verify(struct thread_data *td)
        td_set_runstate(td, TD_VERIFYING);
 
        io_u = NULL;
+       io_bytes = 0;
        while (!td->terminate) {
                enum fio_ddir ddir;
                int ret2, full;
@@ -438,18 +440,27 @@ static void do_verify(struct thread_data *td)
                if (flow_threshold_exceeded(td))
                        continue;
 
-               io_u = __get_io_u(td);
-               if (!io_u)
-                       break;
+               if (!td->o.experimental_verify) {
+                       io_u = __get_io_u(td);
+                       if (!io_u)
+                               break;
 
-               if (get_next_verify(td, io_u)) {
-                       put_io_u(td, io_u);
-                       break;
-               }
+                       if (get_next_verify(td, io_u)) {
+                               put_io_u(td, io_u);
+                               break;
+                       }
 
-               if (td_io_prep(td, io_u)) {
-                       put_io_u(td, io_u);
-                       break;
+                       if (td_io_prep(td, io_u)) {
+                               put_io_u(td, io_u);
+                               break;
+                       }
+               } else {
+                       io_u = get_io_u(td);
+                       if (!io_u)
+                               break;
+
+                       if (io_u->buflen + io_bytes > verify_bytes)
+                               break;
                }
 
                if (td->o.verify_async)
@@ -480,6 +491,7 @@ static void do_verify(struct thread_data *td)
                                io_u->xfer_buflen = io_u->resid;
                                io_u->xfer_buf += bytes;
                                io_u->offset += bytes;
+                               io_bytes += bytes;
 
                                if (ddir_rw(io_u->ddir))
                                        td->ts.short_io_u[io_u->ddir]++;
@@ -495,6 +507,7 @@ sync_done:
                                if (ret < 0)
                                        break;
                        }
+                       io_bytes += io_u->xfer_buflen;
                        continue;
                case FIO_Q_QUEUED:
                        break;
@@ -529,15 +542,18 @@ sync_done:
                                min_events = 1;
 
                        do {
+                               unsigned long bytes = 0;
+
                                /*
                                 * Reap required number of io units, if any,
                                 * and do the verification on them through
                                 * the callback handler
                                 */
-                               if (io_u_queued_complete(td, min_events, NULL) < 0) {
+                               if (io_u_queued_complete(td, min_events, &bytes) < 0) {
                                        ret = -1;
                                        break;
                                }
+                               io_bytes += bytes;
                        } while (full && (td->cur_depth > td->o.iodepth_low));
                }
                if (ret < 0)
@@ -1174,6 +1190,8 @@ static void *thread_main(void *data)
 
        clear_state = 0;
        while (keep_running(td)) {
+               uint64_t write_bytes;
+
                fio_gettime(&td->start, NULL);
                memcpy(&td->bw_sample_time, &td->start, sizeof(td->start));
                memcpy(&td->iops_sample_time, &td->start, sizeof(td->start));
@@ -1194,7 +1212,9 @@ static void *thread_main(void *data)
 
                prune_io_piece_log(td);
 
+               write_bytes = td->io_bytes[DDIR_WRITE];
                do_io(td);
+               write_bytes = td->io_bytes[DDIR_WRITE] - write_bytes;
 
                clear_state = 1;
 
@@ -1223,7 +1243,7 @@ static void *thread_main(void *data)
 
                fio_gettime(&td->start, NULL);
 
-               do_verify(td);
+               do_verify(td, write_bytes);
 
                td->ts.runtime[DDIR_READ] += utime_since_now(&td->start);
 
diff --git a/fio.h b/fio.h
index c5e2bf13414ebbb58d186bb1cddaaabed2919e05..ed793ae560e180bc4255315de441c00be27b4f8b 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -159,6 +159,7 @@ struct thread_options {
        unsigned int verify_async;
        unsigned long long verify_backlog;
        unsigned int verify_batch;
+       unsigned int experimental_verify;
        unsigned int use_thread;
        unsigned int unlink;
        unsigned int do_disk_util;
diff --git a/io_u.c b/io_u.c
index 1658fb20896e10490161e4b71f3d2c362ede4d53..f020cac38af38e5d2ebb150c059564f023b14b18 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -183,7 +183,8 @@ static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
         * any stored write metadata, just return a random offset
         */
        if (!td->o.verifysort_nr || !(ddir == DDIR_READ && td->o.do_verify &&
-           td->o.verify != VERIFY_NONE && td_random(td)))
+           td->o.verify != VERIFY_NONE && td_random(td)) ||
+           td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE)
                return get_off_from_method(td, f, ddir, b);
 
        if (!flist_empty(&td->next_rand_list)) {
@@ -544,6 +545,12 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td)
 {
        enum fio_ddir ddir;
 
+       /*
+        * If verify phase started, it's always a READ
+        */
+       if (td->runstate == TD_VERIFYING)
+               return DDIR_READ;
+
        /*
         * see if it's time to fsync
         */
@@ -1418,7 +1425,8 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
 
                if (td_write(td) && idx == DDIR_WRITE &&
                    td->o.do_verify &&
-                   td->o.verify != VERIFY_NONE)
+                   td->o.verify != VERIFY_NONE &&
+                   !td->o.experimental_verify)
                        log_io_piece(td, io_u);
 
                icd->bytes_done[idx] += bytes;
index 96ae8146b8cc16e62defedbfe3baa1a4050487e9..8255072e4806ed2b871db7077fcaed62a0f92299 100644 (file)
--- a/libfio.c
+++ b/libfio.c
@@ -82,7 +82,7 @@ static void reset_io_counters(struct thread_data *td)
        /*
         * reset file done count if we are to start over
         */
-       if (td->o.time_based || td->o.loops)
+       if (td->o.time_based || td->o.loops || td->o.do_verify)
                td->nr_done_files = 0;
 }