verify: add new experimental mode that requires no meta data
[fio.git] / backend.c
index fd73eda08a326c073cf3a3e22891b5001a1fa535..507faa9992e7325d4c80de368e43f2a779893739 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -34,7 +34,9 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <sys/ipc.h>
+#ifndef FIO_NO_HAVE_SHM_H
 #include <sys/shm.h>
+#endif
 #include <sys/mman.h>
 
 #include "fio.h"
@@ -62,6 +64,7 @@ struct io_log *agg_io_log[DDIR_RWDIR_CNT];
 
 int groupid = 0;
 unsigned int thread_number = 0;
+unsigned int stat_number = 0;
 unsigned int nr_process = 0;
 unsigned int nr_thread = 0;
 int shm_id = 0;
@@ -390,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");
@@ -418,7 +422,9 @@ 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;
 
                update_tv_cache(td);
@@ -434,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)
@@ -453,6 +468,8 @@ static void do_verify(struct thread_data *td)
                else
                        io_u->end_io = verify_io_u;
 
+               ddir = io_u->ddir;
+
                ret = td_io_queue(td, io_u);
                switch (ret) {
                case FIO_Q_COMPLETED:
@@ -474,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]++;
@@ -489,6 +507,7 @@ sync_done:
                                if (ret < 0)
                                        break;
                        }
+                       io_bytes += io_u->xfer_buflen;
                        continue;
                case FIO_Q_QUEUED:
                        break;
@@ -504,7 +523,7 @@ sync_done:
                        break;
                }
 
-               if (break_on_this_error(td, io_u->ddir, &ret))
+               if (break_on_this_error(td, ddir, &ret))
                        break;
 
                /*
@@ -523,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)
@@ -800,6 +822,10 @@ static void cleanup_io_u(struct thread_data *td)
                io_u = flist_entry(entry, struct io_u, list);
 
                flist_del(&io_u->list);
+
+               if (td->io_ops->io_u_free)
+                       td->io_ops->io_u_free(td, io_u);
+
                fio_memfree(io_u, sizeof(*io_u));
        }
 
@@ -882,6 +908,16 @@ static int init_io_u(struct thread_data *td)
                io_u->index = i;
                io_u->flags = IO_U_F_FREE;
                flist_add(&io_u->list, &td->io_u_freelist);
+
+               if (td->io_ops->io_u_init) {
+                       int ret = td->io_ops->io_u_init(td, io_u);
+
+                       if (ret) {
+                               log_err("fio: failed to init engine data: %d\n", ret);
+                               return 1;
+                       }
+               }
+
                p += max_bs;
        }
 
@@ -994,6 +1030,8 @@ static void *thread_main(void *data)
        } else
                td->pid = gettid();
 
+       fio_local_clock_init(td->o.use_thread);
+
        dprint(FD_PROCESS, "jobs pid=%d started\n", (int) td->pid);
 
        INIT_FLIST_HEAD(&td->io_u_freelist);
@@ -1003,6 +1041,7 @@ static void *thread_main(void *data)
        INIT_FLIST_HEAD(&td->io_hist_list);
        INIT_FLIST_HEAD(&td->verify_list);
        INIT_FLIST_HEAD(&td->trim_list);
+       INIT_FLIST_HEAD(&td->next_rand_list);
        pthread_mutex_init(&td->io_u_lock, NULL);
        td->io_hist_tree = RB_ROOT;
 
@@ -1052,7 +1091,7 @@ static void *thread_main(void *data)
                goto err;
        }
 
-#ifdef FIO_HAVE_LIBNUMA
+#ifdef CONFIG_LIBNUMA
        /* numa node setup */
        if (td->o.numa_cpumask_set || td->o.numa_memmask_set) {
                int ret;
@@ -1151,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));
@@ -1171,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;
 
@@ -1200,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);
 
@@ -1270,8 +1313,8 @@ err:
                verify_async_exit(td);
 
        close_and_free_files(td);
-       close_ioengine(td);
        cleanup_io_u(td);
+       close_ioengine(td);
        cgroup_shutdown(td, &cgroup_mnt);
 
        if (td->o.cpumask_set) {
@@ -1382,7 +1425,7 @@ static void reap_threads(unsigned int *nr_running, unsigned int *t_rate,
                        if (WIFSIGNALED(status)) {
                                int sig = WTERMSIG(status);
 
-                               if (sig != SIGTERM)
+                               if (sig != SIGTERM && sig != SIGUSR2)
                                        log_err("fio: pid=%d, got signal=%d\n",
                                                        (int) td->pid, sig);
                                td->sig = sig;