Merge branch 'dedupe_bugfix' of https://github.com/bardavid/fio
[fio.git] / rate-submit.c
index cf00d9bc75c56f057b41a337ae8bdc740aebaa66..13dbe7a2e9ff8f3face1619e750b83018ba222df 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2015 Jens Axboe <axboe@kernel.dk>
  *
  */
+#include <assert.h>
 #include "fio.h"
 #include "ioengines.h"
 #include "lib/getrusage.h"
 
 static void check_overlap(struct io_u *io_u)
 {
-       int i;
+       int i, res;
        struct thread_data *td;
-       bool overlap = false;
 
-       do {
-               /*
-                * Allow only one thread to check for overlap at a
-                * 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) {
-                       if (td->runstate <= TD_SETTING_UP ||
-                               td->runstate >= TD_FINISHING ||
-                               !td->o.serialize_overlap ||
-                               td->o.io_submit_mode != IO_MODE_OFFLOAD)
-                               continue;
-
-                       overlap = in_flight_overlap(&td->io_u_all, io_u);
-                       if (overlap) {
-                               pthread_mutex_unlock(&overlap_check);
-                               break;
-                       }
-               }
-       } while (overlap);
+       /*
+        * Allow only one thread to check for overlap at a 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 no overlap is 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.
+        */
+       res = pthread_mutex_lock(&overlap_check);
+       assert(res == 0);
+
+retry:
+       for_each_td(td, i) {
+               if (td->runstate <= TD_SETTING_UP ||
+                   td->runstate >= TD_FINISHING ||
+                   !td->o.serialize_overlap ||
+                   td->o.io_submit_mode != IO_MODE_OFFLOAD)
+                       continue;
+
+               if (!in_flight_overlap(&td->io_u_all, io_u))
+                       continue;
+
+               res = pthread_mutex_unlock(&overlap_check);
+               assert(res == 0);
+               res = pthread_mutex_lock(&overlap_check);
+               assert(res == 0);
+               goto retry;
+       }
 }
 
 static int io_workqueue_fn(struct submit_worker *sw,
@@ -95,8 +97,11 @@ static int io_workqueue_fn(struct submit_worker *sw,
                        td->cur_depth -= ret;
        }
 
-       if (error || td->error)
+       if (error || td->error) {
+               pthread_mutex_lock(&td->io_u_lock);
                pthread_cond_signal(&td->parent->free_cond);
+               pthread_mutex_unlock(&td->io_u_lock);
+       }
 
        return 0;
 }