Recent changes (master)

Jens Axboe
2018-10-16T19:50:22Z

The following changes since commit ee6ce26c029dbdb62184d2f011fdab61d3429d82:

options: kill 'use_os_rand' (2018-10-08 13:43:23 -0600)

are available in the git repository at:

git://git.kernel.dk/fio.git master

for you to fetch changes up to d5dbacf662b1cc3fb09b5cd70b236ab98d1c0dbe:

Merge branch 'offload-serialize-overlap2' of https://github.com/vincentkfu/fio (2018-10-15 14:09:18 -0600)

----------------------------------------------------------------
Jens Axboe (1):
Merge branch 'offload-serialize-overlap2' of https://github.com/vincentkfu/fio

Vincent Fu (4):
init: loosen serialize_overlap restrictions
fio: enable overlap checking with offload submission
docs: enable serialize_overlap with io_submit_mode=offload
rate-submit: remove code that can never be executed

HOWTO | 9 +++++++--
backend.c | 8 +++++++-
fio.1 | 11 +++++++++--
fio.h | 3 +++
init.c | 13 +++----------
ioengines.c | 2 ++
rate-submit.c | 37 +++++++++++++++++++++++++++++++++----
7 files changed, 64 insertions(+), 19 deletions(-)

---

Diff of recent changes:

diff --git a/HOWTO b/HOWTO
index a2503e9..72ef872 100644
--- a/HOWTO
+++ b/HOWTO
@@ -2339,8 +2339,13 @@ I/O depth
``serialize_overlap`` tells fio to avoid provoking this behavior by explicitly
serializing in-flight I/Os that have a non-zero overlap. Note that setting
this option can reduce both performance and the :option:`iodepth` achieved.
- Additionally this option does not work when :option:`io_submit_mode` is set to
- offload. Default: false.
+
+ This option only applies to I/Os issued for a single job except when it is
+ enabled along with :option:`io_submit_mode`=offload. In offload mode, fio
+ will check for overlap among all I/Os submitted by offload jobs with :option:`serialize_overlap`
+ enabled. Threads must be used for all such jobs.
+
+ Default: false.

.. option:: io_submit_mode=str

diff --git a/backend.c b/backend.c
index 76e456f..cc3c4e7 100644
--- 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.1 b/fio.1
index bf181b3..7691b2b 100644
--- a/fio.1
+++ b/fio.1
@@ -2070,8 +2070,15 @@ changing data and the overlapping region has a non-zero size. Setting
\fBserialize_overlap\fR tells fio to avoid provoking this behavior by explicitly
serializing in-flight I/Os that have a non-zero overlap. Note that setting
this option can reduce both performance and the \fBiodepth\fR achieved.
-Additionally this option does not work when \fBio_submit_mode\fR is set to
-offload. Default: false.
+.RS
+.P
+This option only applies to I/Os issued for a single job except when it is
+enabled along with \fBio_submit_mode\fR=offload. In offload mode, fio
+will check for overlap among all I/Os submitted by offload jobs with \fBserialize_overlap\fR
+enabled. Threads must be used for all such jobs.
+.P
+Default: false.
+.RE
.TP
.BI io_submit_mode \fR=\fPstr
This option controls how fio submits the I/O to the I/O engine. The default
diff --git a/fio.h b/fio.h
index 53bcda1..e394e16 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/init.c b/init.c
index 1eddc6f..a2b70c4 100644
--- a/init.c
+++ b/init.c
@@ -744,19 +744,12 @@ static int fixup_options(struct thread_data *td)
/*
* There's no need to check for in-flight overlapping IOs if the job
* isn't changing data or the maximum iodepth is guaranteed to be 1
+ * when we are not in offload mode
*/
if (o->serialize_overlap && !(td->flags & TD_F_READ_IOLOG) &&
- (!(td_write(td) || td_trim(td)) || o->iodepth == 1))
+ (!(td_write(td) || td_trim(td)) || o->iodepth == 1) &&
+ o->io_submit_mode != IO_MODE_OFFLOAD)
o->serialize_overlap = 0;
- /*
- * Currently can't check for overlaps in offload mode
- */
- if (o->serialize_overlap && o->io_submit_mode == IO_MODE_OFFLOAD) {
- log_err("fio: checking for in-flight overlaps when the "
- "io_submit_mode is offload is not supported\n");
- o->serialize_overlap = 0;
- ret |= warnings_fatal;
- }

if (o->nr_files > td->files_index)
o->nr_files = td->files_index;
diff --git a/ioengines.c b/ioengines.c
index ba02952..47f606a 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 2f02fe2..68ad755 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);
@@ -50,10 +83,6 @@ static int io_workqueue_fn(struct submit_worker *sw,
ret = io_u_queued_complete(td, min_evts);
if (ret > 0)
td->cur_depth -= ret;
- } else if (ret == FIO_Q_BUSY) {
- ret = io_u_queued_complete(td, td->cur_depth);
- if (ret > 0)
- td->cur_depth -= ret;
}

return 0;