io_u timeout handling
[fio.git] / fio.c
diff --git a/fio.c b/fio.c
index 95e06dd8e045136ce9954a8e759aef3dac09a7d0..fad4cca76bbe2cb9781ad10183e0ab369d126ff2 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -160,9 +160,19 @@ static void cleanup_pending_aio(struct thread_data *td)
                list_for_each_safe(entry, n, &td->io_u_busylist) {
                        io_u = list_entry(entry, struct io_u, list);
 
-                       r = td->io_ops->cancel(td, io_u);
-                       if (!r)
+                       /*
+                        * if the io_u isn't in flight, then that generally
+                        * means someone leaked an io_u. complain but fix
+                        * it up, so we don't stall here.
+                        */
+                       if ((io_u->flags & IO_U_F_FLIGHT) == 0) {
+                               log_err("fio: non-busy IO on busy list\n");
                                put_io_u(td, io_u);
+                       } else {
+                               r = td->io_ops->cancel(td, io_u);
+                               if (!r)
+                                       put_io_u(td, io_u);
+                       }
                }
        }
 
@@ -197,7 +207,7 @@ requeue:
                put_io_u(td, io_u);
                return 1;
        } else if (ret == FIO_Q_QUEUED) {
-               if (io_u_queued_complete(td, 1, NULL))
+               if (io_u_queued_complete(td, 1, NULL) < 0)
                        return 1;
        } else if (ret == FIO_Q_COMPLETED) {
                if (io_u->error) {
@@ -248,15 +258,20 @@ static void do_verify(struct thread_data *td)
                if (!io_u)
                        break;
 
-               if (runtime_exceeded(td, &io_u->start_time))
+               if (runtime_exceeded(td, &io_u->start_time)) {
+                       put_io_u(td, io_u);
                        break;
+               }
 
-               if (get_next_verify(td, io_u))
+               if (get_next_verify(td, io_u)) {
+                       put_io_u(td, io_u);
                        break;
+               }
 
-               if (td_io_prep(td, io_u))
+               if (td_io_prep(td, io_u)) {
+                       put_io_u(td, io_u);
                        break;
-
+               }
 requeue:
                ret = td_io_queue(td, io_u);
 
@@ -272,7 +287,7 @@ requeue:
                                goto requeue;
                        }
                        ret = io_u_sync_complete(td, io_u, verify_io_u);
-                       if (ret)
+                       if (ret < 0)
                                break;
                        continue;
                case FIO_Q_QUEUED:
@@ -306,13 +321,10 @@ requeue:
                 * 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, verify_io_u))
+               if (io_u_queued_complete(td, min_events, verify_io_u) < 0)
                        break;
        }
 
-       if (io_u)
-               put_io_u(td, io_u);
-
        if (td->cur_depth)
                cleanup_pending_aio(td);
 
@@ -551,9 +563,12 @@ static int init_io_u(struct thread_data *td)
                        fill_rand_buf(io_u, max_bs);
 
                io_u->index = i;
+               io_u->flags = IO_U_F_FREE;
                list_add(&io_u->list, &td->io_u_freelist);
        }
 
+       io_u_init_timeout();
+
        return 0;
 }
 
@@ -702,6 +717,7 @@ static void *thread_main(void *data)
        }
 
        fio_gettime(&td->epoch, NULL);
+       memcpy(&td->timeout_end, &td->epoch, sizeof(td->epoch));
        getrusage(RUSAGE_SELF, &td->ts.ru_start);
 
        runtime[0] = runtime[1] = 0;
@@ -769,7 +785,7 @@ err:
        close_ioengine(td);
        cleanup_io_u(td);
        td_set_runstate(td, TD_EXITED);
-       return (void *) td->error;
+       return (void *) (unsigned long) td->error;
 }
 
 /*
@@ -792,7 +808,7 @@ static int fork_main(int shmid, int offset)
        td = data + offset * sizeof(struct thread_data);
        ret = thread_main(td);
        shmdt(data);
-       return (int) ret;
+       return (int) (unsigned long) ret;
 }
 
 /*
@@ -820,9 +836,14 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate)
                         * check if someone quit or got killed in an unusual way
                         */
                        ret = waitpid(td->pid, &status, WNOHANG);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               if (errno == ECHILD) {
+                                       log_err("fio: pid=%d disappeared\n", td->pid);
+                                       td_set_runstate(td, TD_REAPED);
+                                       goto reaped;
+                               }
                                perror("waitpid");
-                       else if ((ret == td->pid) && WIFSIGNALED(status)) {
+                       else if ((ret == td->pid) && WIFSIGNALED(status)) {
                                int sig = WTERMSIG(status);
 
                                log_err("fio: pid=%d, got signal=%d\n", td->pid, sig);
@@ -852,9 +873,14 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate)
                        int status;
 
                        ret = waitpid(td->pid, &status, 0);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               if (errno == ECHILD) {
+                                       log_err("fio: pid=%d disappeared\n", td->pid);
+                                       td_set_runstate(td, TD_REAPED);
+                                       goto reaped;
+                               }
                                perror("waitpid");
-                       else if (WIFEXITED(status) && WEXITSTATUS(status)) {
+                       else if (WIFEXITED(status) && WEXITSTATUS(status)) {
                                if (!exit_value)
                                        exit_value++;
                        }