->getevents() should take unsigned args
[fio.git] / fio.c
diff --git a/fio.c b/fio.c
index 1e69ce4228c624f3775a95e3299bde84c1e0baef..e9b27d9ccef7405583065434f60f858c09f02cea 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -446,6 +446,13 @@ static void do_io(struct thread_data *td)
                        break;
                }
 
+               /*
+                * Add verification end_io handler, if asked to verify
+                * a previously written file.
+                */
+               if (td->o.verify != VERIFY_NONE)
+                       io_u->end_io = verify_io_u;
+
                ret = td_io_queue(td, io_u);
                switch (ret) {
                case FIO_Q_COMPLETED:
@@ -650,10 +657,12 @@ static int init_io_u(struct thread_data *td)
                memset(io_u, 0, sizeof(*io_u));
                INIT_LIST_HEAD(&io_u->list);
 
-               io_u->buf = p + max_bs * i;
+               if (!(td->io_ops->flags & FIO_NOIO)) {
+                       io_u->buf = p + max_bs * i;
 
-               if (td_write(td))
-                       fill_io_buf(td, io_u, max_bs);
+                       if (td_write(td))
+                               fill_io_buf(td, io_u, max_bs);
+               }
 
                io_u->index = i;
                io_u->flags = IO_U_F_FREE;
@@ -724,6 +733,8 @@ static int keep_running(struct thread_data *td)
 {
        unsigned long long io_done;
 
+       if (td->done)
+               return 0;
        if (td->o.time_based)
                return 1;
        if (td->o.loops) {
@@ -731,7 +742,7 @@ static int keep_running(struct thread_data *td)
                return 1;
        }
 
-       io_done = td->io_bytes[DDIR_READ] + td->io_bytes[DDIR_WRITE];
+       io_done = td->io_bytes[DDIR_READ] + td->io_bytes[DDIR_WRITE] + td->io_skip_bytes;
        if (io_done < td->o.size)
                return 1;
 
@@ -753,7 +764,8 @@ static int clear_io_state(struct thread_data *td)
 
        td->last_was_sync = 0;
 
-       td->nr_done_files = 0;
+       if (td->o.time_based)
+               td->nr_done_files = 0;
 
        for_each_file(td, f, i)
                td_io_close_file(td, f);
@@ -775,9 +787,8 @@ static int clear_io_state(struct thread_data *td)
  */
 static void *thread_main(void *data)
 {
-       unsigned long long runtime[2];
+       unsigned long long runtime[2], elapsed;
        struct thread_data *td = data;
-       unsigned long elapsed;
        int clear_state;
 
        if (!td->o.use_thread)
@@ -817,7 +828,7 @@ static void *thread_main(void *data)
                goto err;
        }
 
-       if (td->ioprio) {
+       if (td->ioprio_set) {
                if (ioprio_set(IOPRIO_WHO_PROCESS, 0, td->ioprio) == -1) {
                        td_verror(td, errno, "ioprio_set");
                        goto err;
@@ -891,7 +902,9 @@ static void *thread_main(void *data)
                if (td->error || td->terminate)
                        break;
 
-               if (td->o.verify == VERIFY_NONE)
+               if (!td->o.do_verify ||
+                   td->o.verify == VERIFY_NONE ||
+                   (td->io_ops->flags & FIO_UNIDIR))
                        continue;
 
                if (clear_io_state(td))
@@ -908,8 +921,8 @@ static void *thread_main(void *data)
        }
 
        update_rusage_stat(td);
-       td->ts.runtime[0] = runtime[0] / 1000;
-       td->ts.runtime[1] = runtime[1] / 1000;
+       td->ts.runtime[0] = (runtime[0] + 999) / 1000;
+       td->ts.runtime[1] = (runtime[1] + 999) / 1000;
        td->ts.total_run_time = mtime_since_now(&td->epoch);
        td->ts.io_bytes[0] = td->io_bytes[0];
        td->ts.io_bytes[1] = td->io_bytes[1];
@@ -920,8 +933,6 @@ static void *thread_main(void *data)
                finish_log(td, td->ts.slat_log, "slat");
        if (td->ts.clat_log)
                finish_log(td, td->ts.clat_log, "clat");
-       if (td->o.write_iolog_file)
-               write_iolog_close(td);
        if (td->o.exec_postrun) {
                if (system(td->o.exec_postrun) < 0)
                        log_err("fio: postrun %s failed\n", td->o.exec_postrun);
@@ -936,6 +947,13 @@ err:
        close_files(td);
        close_ioengine(td);
        cleanup_io_u(td);
+
+       /*
+        * do this very late, it will log file closing as well
+        */
+       if (td->o.write_iolog_file)
+               write_iolog_close(td);
+
        options_mem_free(td);
        td_set_runstate(td, TD_EXITED);
        return (void *) (unsigned long) td->error;
@@ -970,12 +988,12 @@ static int fork_main(int shmid, int offset)
 static void reap_threads(int *nr_running, int *t_rate, int *m_rate)
 {
        struct thread_data *td;
-       int i, cputhreads, pending, status, ret;
+       int i, cputhreads, realthreads, pending, status, ret;
 
        /*
         * reap exited threads (TD_EXITED -> TD_REAPED)
         */
-       pending = cputhreads = 0;
+       realthreads = pending = cputhreads = 0;
        for_each_td(td, i) {
                int flags = 0;
 
@@ -985,6 +1003,8 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate)
                 */
                if (td->io_ops && !strcmp(td->io_ops->name, "cpuio"))
                        cputhreads++;
+               else
+                       realthreads++;
 
                if (!td->pid || td->runstate == TD_REAPED)
                        continue;
@@ -1051,7 +1071,7 @@ reaped:
                        exit_value++;
        }
 
-       if (*nr_running == cputhreads && !pending)
+       if (*nr_running == cputhreads && !pending && realthreads)
                terminate_threads(TERMINATE_ALL);
 }