From c06379a65d467bdcc782d7e1aa067e6391cd5a68 Mon Sep 17 00:00:00 2001 From: Vincent Fu Date: Mon, 1 Oct 2018 14:22:10 -0400 Subject: [PATCH] fio: enable overlap checking with offload submission 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 --- backend.c | 8 +++++++- fio.h | 3 +++ ioengines.c | 2 ++ rate-submit.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/backend.c b/backend.c index 76e456f1..cc3c4e78 100644 --- a/backend.c +++ b/backend.c @@ -29,6 +29,7 @@ #include #include #include +#include #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 53bcda13..e394e165 100644 --- 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 diff --git a/ioengines.c b/ioengines.c index ba02952b..47f606a7 100644 --- a/ioengines.c +++ b/ioengines.c @@ -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)); diff --git a/rate-submit.c b/rate-submit.c index 2f02fe2b..8ecd285c 100644 --- a/rate-submit.c +++ b/rate-submit.c @@ -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); -- 2.25.1