fio: fix aio trim completion latencies
[fio.git] / rate-submit.c
index 68ad755d948056c0ff9fabc0a26a14961f410a05..cf00d9bc75c56f057b41a337ae8bdc740aebaa66 100644 (file)
@@ -21,6 +21,14 @@ static void check_overlap(struct io_u *io_u)
                 * time to prevent two threads from thinking the coast
                 * is clear and then submitting IOs that overlap with
                 * each other
+                *
+                * If an overlap is found, release the lock and
+                * re-acquire it before checking again to give other
+                * threads a chance to make progress
+                *
+                * If an overlap is not found, release the lock when the
+                * io_u's IO_U_F_FLIGHT flag is set so that this io_u
+                * can be checked by other threads as they assess overlap
                 */
                pthread_mutex_lock(&overlap_check);
                for_each_td(td, i) {
@@ -45,7 +53,7 @@ static int io_workqueue_fn(struct submit_worker *sw,
        struct io_u *io_u = container_of(work, struct io_u, work);
        const enum fio_ddir ddir = io_u->ddir;
        struct thread_data *td = sw->priv;
-       int ret;
+       int ret, error;
 
        if (td->o.serialize_overlap)
                check_overlap(io_u);
@@ -63,12 +71,14 @@ static int io_workqueue_fn(struct submit_worker *sw,
                ret = io_u_queued_complete(td, 1);
                if (ret > 0)
                        td->cur_depth -= ret;
+               else if (ret < 0)
+                       break;
                io_u_clear(td, io_u, IO_U_F_FLIGHT);
        } while (1);
 
        dprint(FD_RATE, "io_u %p ret %d by %u\n", io_u, ret, gettid());
 
-       io_queue_event(td, io_u, &ret, ddir, NULL, 0, NULL);
+       error = io_queue_event(td, io_u, &ret, ddir, NULL, 0, NULL);
 
        if (ret == FIO_Q_COMPLETED)
                td->cur_depth--;
@@ -85,6 +95,9 @@ static int io_workqueue_fn(struct submit_worker *sw,
                        td->cur_depth -= ret;
        }
 
+       if (error || td->error)
+               pthread_cond_signal(&td->parent->free_cond);
+
        return 0;
 }
 
@@ -92,6 +105,8 @@ static bool io_workqueue_pre_sleep_flush_fn(struct submit_worker *sw)
 {
        struct thread_data *td = sw->priv;
 
+       if (td->error)
+               return false;
        if (td->io_u_queued || td->cur_depth || td->io_u_in_flight)
                return true;
 
@@ -150,6 +165,9 @@ static int io_workqueue_init_worker_fn(struct submit_worker *sw)
        if (td_io_init(td))
                goto err_io_init;
 
+       if (td->io_ops->post_init && td->io_ops->post_init(td))
+               goto err_io_init;
+
        set_epoch_time(td, td->o.log_unix_epoch);
        fio_getrusage(&td->ru_start);
        clear_io_state(td, 1);