Allow override of CFLAGS
[fio.git] / backend.c
index 507faa9992e7325d4c80de368e43f2a779893739..218ae2545db8fbf5e29a89ef43f954ac6f25bc9c 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -50,6 +50,8 @@
 #include "lib/rand.h"
 #include "memalign.h"
 #include "server.h"
+#include "lib/getrusage.h"
+#include "idletime.h"
 
 static pthread_t disk_util_thread;
 static struct fio_mutex *disk_thread_mutex;
@@ -216,7 +218,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;
 
@@ -395,10 +397,10 @@ static int break_on_this_error(struct thread_data *td, enum fio_ddir ddir,
  */
 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;
-       uint64_t io_bytes;
        unsigned int i;
 
        dprint(FD_VERIFY, "starting loop\n");
@@ -422,7 +424,6 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
        td_set_runstate(td, TD_VERIFYING);
 
        io_u = NULL;
-       io_bytes = 0;
        while (!td->terminate) {
                enum fio_ddir ddir;
                int ret2, full;
@@ -455,11 +456,37 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
                                break;
                        }
                } else {
-                       io_u = get_io_u(td);
-                       if (!io_u)
+                       if (ddir_rw_sum(bytes_done) + td->o.rw_min_bs > verify_bytes)
                                break;
 
-                       if (io_u->buflen + io_bytes > verify_bytes)
+                       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;
                }
 
@@ -491,7 +518,6 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
                                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]++;
@@ -503,11 +529,10 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
                                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;
                        }
-                       io_bytes += io_u->xfer_buflen;
                        continue;
                case FIO_Q_QUEUED:
                        break;
@@ -542,18 +567,15 @@ 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, &bytes) < 0) {
+                               if (io_u_queued_complete(td, min_events, bytes_done) < 0) {
                                        ret = -1;
                                        break;
                                }
-                               io_bytes += bytes;
                        } while (full && (td->cur_depth > td->o.iodepth_low));
                }
                if (ret < 0)
@@ -592,9 +614,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;
 
@@ -607,7 +632,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;
@@ -811,6 +835,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)
@@ -1186,11 +1212,10 @@ static void *thread_main(void *data)
        }
 
        fio_gettime(&td->epoch, NULL);
-       getrusage(RUSAGE_SELF, &td->ru_start);
-
+       fio_getrusage(&td->ru_start);
        clear_state = 0;
        while (keep_running(td)) {
-               uint64_t write_bytes;
+               uint64_t verify_bytes;
 
                fio_gettime(&td->start, NULL);
                memcpy(&td->bw_sample_time, &td->start, sizeof(td->start));
@@ -1212,9 +1237,7 @@ 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;
+               verify_bytes = do_io(td);
 
                clear_state = 1;
 
@@ -1243,7 +1266,7 @@ static void *thread_main(void *data)
 
                fio_gettime(&td->start, NULL);
 
-               do_verify(td, write_bytes);
+               do_verify(td, verify_bytes);
 
                td->ts.runtime[DDIR_READ] += utime_since_now(&td->start);
 
@@ -1477,6 +1500,8 @@ static void run_threads(void)
 
        if (fio_gtod_offload && fio_start_gtod_thread())
                return;
+       
+       fio_idle_prof_init();
 
        set_sig_handlers();
 
@@ -1534,6 +1559,9 @@ static void run_threads(void)
                }
        }
 
+       /* start idle threads before io threads start to run */
+       fio_idle_prof_start();
+
        set_genesis_time();
 
        while (todo) {
@@ -1696,6 +1724,8 @@ static void run_threads(void)
                        usleep(10000);
        }
 
+       fio_idle_prof_stop();
+
        update_io_ticks();
        fio_unpin_memory();
 }