fio: enable overlap checking with offload submission
authorVincent Fu <vincent.fu@wdc.com>
Mon, 1 Oct 2018 18:22:10 +0000 (14:22 -0400)
committerVincent Fu <vincent.fu@wdc.com>
Mon, 15 Oct 2018 19:57:23 +0000 (15:57 -0400)
Enable use of the serialize_overlap option with
io_submit_mode=offload. Threads with both of these options enabled will
check each other's in-flight IOs for overlap. If overlap is found,
submission of the new IO will be held back until the overlapping IO has
completed.

Threads must be used when fio is run in this mode because jobs need to
access each other's io_u's. io_u's are not allocated from the shared memory
area.

This fixes "fio serialize across jobs"
https://www.spinics.net/lists/fio/msg07133.html

Tested-by: Jeff Furlong <jeff.furlong@wdc.com>
backend.c
fio.h
ioengines.c
rate-submit.c

index 76e456f1295da2d827269c27716ef63cbd33af43..cc3c4e78e9d8ae6b8fd9cdc245272fc395369f34 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -29,6 +29,7 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <math.h>
+#include <pthread.h>
 
 #include "fio.h"
 #include "smalloc.h"
@@ -65,6 +66,7 @@ unsigned int stat_number = 0;
 int shm_id = 0;
 int temp_stall_ts;
 unsigned long done_secs = 0;
+pthread_mutex_t overlap_check = PTHREAD_MUTEX_INITIALIZER;
 
 #define JOB_START_TIMEOUT      (5 * 1000)
 
@@ -567,7 +569,7 @@ static int unlink_all_files(struct thread_data *td)
 /*
  * Check if io_u will overlap an in-flight IO in the queue
  */
-static bool in_flight_overlap(struct io_u_queue *q, struct io_u *io_u)
+bool in_flight_overlap(struct io_u_queue *q, struct io_u *io_u)
 {
        bool overlap;
        struct io_u *check_io_u;
@@ -1872,7 +1874,11 @@ static void *thread_main(void *data)
                         "perhaps try --debug=io option for details?\n",
                         td->o.name, td->io_ops->name);
 
+       if (td->o.serialize_overlap && td->o.io_submit_mode == IO_MODE_OFFLOAD)
+               pthread_mutex_lock(&overlap_check);
        td_set_runstate(td, TD_FINISHING);
+       if (td->o.serialize_overlap && td->o.io_submit_mode == IO_MODE_OFFLOAD)
+               pthread_mutex_unlock(&overlap_check);
 
        update_rusage_stat(td);
        td->ts.total_run_time = mtime_since_now(&td->epoch);
diff --git a/fio.h b/fio.h
index 53bcda1315f9b88858e6cf2f41b37b03b4380bd5..e394e165078a4fa3da53d397cae2791e8e9fe195 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -852,4 +852,7 @@ enum {
 extern void exec_trigger(const char *);
 extern void check_trigger_file(void);
 
+extern bool in_flight_overlap(struct io_u_queue *q, struct io_u *io_u);
+extern pthread_mutex_t overlap_check;
+
 #endif
index ba02952b1f0f8d0c8ae9bebe31e091a0302046aa..47f606a75409c9a2679443ad02ba7f818e6f6ed4 100644 (file)
@@ -288,6 +288,8 @@ enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u)
 
        assert((io_u->flags & IO_U_F_FLIGHT) == 0);
        io_u_set(td, io_u, IO_U_F_FLIGHT);
+       if (td->o.serialize_overlap && td->o.io_submit_mode == IO_MODE_OFFLOAD)
+               pthread_mutex_unlock(&overlap_check);
 
        assert(fio_file_open(io_u->file));
 
index 2f02fe2ba8365dea762051e555b1f28651ee45e3..8ecd285c7d91eba927e762e9ab6e5f422c01836f 100644 (file)
@@ -9,6 +9,36 @@
 #include "lib/getrusage.h"
 #include "rate-submit.h"
 
+static void check_overlap(struct io_u *io_u)
+{
+       int i;
+       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
+                */
+               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);
+}
+
 static int io_workqueue_fn(struct submit_worker *sw,
                           struct workqueue_work *work)
 {
@@ -17,6 +47,9 @@ static int io_workqueue_fn(struct submit_worker *sw,
        struct thread_data *td = sw->priv;
        int ret;
 
+       if (td->o.serialize_overlap)
+               check_overlap(io_u);
+
        dprint(FD_RATE, "io_u %p queued by %u\n", io_u, gettid());
 
        io_u_set(td, io_u, IO_U_F_NO_FILE_PUT);