configure: add endian check
[fio.git] / backend.c
index a71d768d22d89437e4a6cde828c24c36bb28ecbf..e025dbffe01b4f6a667f2b7d561603d1664eef06 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -216,7 +216,7 @@ static int __check_min_rate(struct thread_data *td, struct timeval *now,
 }
 
 static int check_min_rate(struct thread_data *td, struct timeval *now,
-                         unsigned long *bytes_done)
+                         uint64_t *bytes_done)
 {
        int ret = 0;
 
@@ -393,8 +393,9 @@ 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)
 {
+       uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
        struct fio_file *f;
        struct io_u *io_u;
        int ret, min_events;
@@ -422,6 +423,7 @@ static void do_verify(struct thread_data *td)
 
        io_u = NULL;
        while (!td->terminate) {
+               enum fio_ddir ddir;
                int ret2, full;
 
                update_tv_cache(td);
@@ -437,18 +439,53 @@ 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 {
+                       if (ddir_rw_sum(bytes_done) + td->o.rw_min_bs > verify_bytes)
+                               break;
+
+                       while ((io_u = get_io_u(td)) != NULL) {
+                               /*
+                                * We are only interested in the places where
+                                * we wrote or trimmed IOs. Turn those into
+                                * reads for verification purposes.
+                                */
+                               if (io_u->ddir == DDIR_READ) {
+                                       /*
+                                        * Pretend we issued it for rwmix
+                                        * accounting
+                                        */
+                                       td->io_issues[DDIR_READ]++;
+                                       put_io_u(td, io_u);
+                                       continue;
+                               } else if (io_u->ddir == DDIR_TRIM) {
+                                       io_u->ddir = DDIR_READ;
+                                       io_u->flags |= IO_U_F_TRIMMED;
+                                       break;
+                               } else if (io_u->ddir == DDIR_WRITE) {
+                                       io_u->ddir = DDIR_READ;
+                                       break;
+                               } else {
+                                       put_io_u(td, io_u);
+                                       continue;
+                               }
+                       }
+
+                       if (!io_u)
+                               break;
                }
 
                if (td->o.verify_async)
@@ -456,6 +493,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:
@@ -488,7 +527,7 @@ static void do_verify(struct thread_data *td)
                                requeue_io_u(td, &io_u);
                        } else {
 sync_done:
-                               ret = io_u_sync_complete(td, io_u, NULL);
+                               ret = io_u_sync_complete(td, io_u, bytes_done);
                                if (ret < 0)
                                        break;
                        }
@@ -507,7 +546,7 @@ sync_done:
                        break;
                }
 
-               if (break_on_this_error(td, io_u->ddir, &ret))
+               if (break_on_this_error(td, ddir, &ret))
                        break;
 
                /*
@@ -531,7 +570,7 @@ sync_done:
                                 * 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_done) < 0) {
                                        ret = -1;
                                        break;
                                }
@@ -573,9 +612,12 @@ static int io_bytes_exceeded(struct thread_data *td)
 /*
  * Main IO worker function. It retrieves io_u's to process and queues
  * and reaps them, checking for rate and errors along the way.
+ *
+ * Returns number of bytes written and trimmed.
  */
-static void do_io(struct thread_data *td)
+static uint64_t do_io(struct thread_data *td)
 {
+       uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
        unsigned int i;
        int ret = 0;
 
@@ -588,7 +630,6 @@ static void do_io(struct thread_data *td)
                (!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td) ||
                td->o.time_based) {
                struct timeval comp_time;
-               unsigned long bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
                int min_evts = 0;
                struct io_u *io_u;
                int ret2, full;
@@ -792,6 +833,8 @@ sync_done:
         */
        if (!ddir_rw_sum(td->this_io_bytes))
                td->done = 1;
+
+       return bytes_done[DDIR_WRITE] + bytes_done[DDIR_TRIM];
 }
 
 static void cleanup_io_u(struct thread_data *td)
@@ -1011,6 +1054,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);
@@ -1020,6 +1065,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;
 
@@ -1069,7 +1115,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;
@@ -1168,6 +1214,8 @@ static void *thread_main(void *data)
 
        clear_state = 0;
        while (keep_running(td)) {
+               uint64_t verify_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));
@@ -1188,7 +1236,7 @@ static void *thread_main(void *data)
 
                prune_io_piece_log(td);
 
-               do_io(td);
+               verify_bytes = do_io(td);
 
                clear_state = 1;
 
@@ -1217,7 +1265,7 @@ static void *thread_main(void *data)
 
                fio_gettime(&td->start, NULL);
 
-               do_verify(td);
+               do_verify(td, verify_bytes);
 
                td->ts.runtime[DDIR_READ] += utime_since_now(&td->start);