Hi, I was trying to use the async_verify option. Looks like if we use this option for synchronous I/O, then it really doesnt do anything as after every I/O is completed, we still need the asynchronous verify thread to complete the verification and release the io_u so the main thread can allocate this io_u for the next I/O. So to remove this bottle neck I added a new option extra_buff_count. This takes an integer and the code will allocate that many more extra io_us. This way when the main thread has completed the I/O it will have extra io_u and buffers to issue more I/Os while the asynchronous verify threads do their job. This can be used with both synchronous and libaio contexts. Thanks -radha
diff --git a/HOWTO b/HOWTO index cdd6473..71efd10 100644 --- a/HOWTO +++ b/HOWTO @@ -872,7 +872,12 @@ verify_async=int Fio will normally verify IO inline from the submitting verify_async_cpus=str Tell fio to set the given CPU affinity on the async IO verification threads. See cpus_allowed for the format used. - + +extra_buff_count=int Allocate extra I/O buffers to continue issuing + IO to the file/device. This can be used to keep the device + busy with I/Os while the data verification is being + done asynchronously. + stonewall Wait for preceeding jobs in the job file to exit, before starting this one. Can be used to insert serialization points in the job file. A stone wall also implies starting diff --git a/fio.1 b/fio.1 index 4445d0a..8bee99d 100644 --- a/fio.1 +++ b/fio.1 @@ -627,6 +627,11 @@ allows them to have IO in flight while verifies are running. Tell fio to set the given CPU affinity on the async IO verification threads. See \fBcpus_allowed\fP for the format used. .TP +.BI extra_buff_count \fR=\fPint +Allocate extra I/O buffers to continue issuing IO to the file/device. +This can be used to keep the device busy with I/Os while the data verification +is being done asynchronously. +.TP .B stonewall Wait for preceeding jobs in the job file to exit before starting this one. \fBstonewall\fR implies \fBnew_group\fR. diff --git a/fio.c b/fio.c index 8f8bb56..ff8d0e7 100644 --- a/fio.c +++ b/fio.c @@ -534,7 +534,8 @@ sync_done: * if we can queue more, do so. but check if there are * completed io_u's first. */ - full = queue_full(td) || ret == FIO_Q_BUSY; + full = queue_full(td) || ret == FIO_Q_BUSY || + td->cur_depth == td->o.iodepth; if (full || !td->o.iodepth_batch_complete) { min_events = td->o.iodepth_batch_complete; if (full && !min_events) @@ -686,7 +687,8 @@ sync_done: /* * See if we need to complete some commands */ - full = queue_full(td) || ret == FIO_Q_BUSY; + full = queue_full(td) || ret == FIO_Q_BUSY || + td->cur_depth == td->o.iodepth; if (full || !td->o.iodepth_batch_complete) { min_evts = td->o.iodepth_batch_complete; if (full && !min_evts) @@ -787,7 +789,7 @@ static int init_io_u(struct thread_data *td) int cl_align, i, max_units; char *p; - max_units = td->o.iodepth; + max_units = td->o.iodepth + td->o.extra_buff_count; max_bs = max(td->o.max_bs[DDIR_READ], td->o.max_bs[DDIR_WRITE]); td->orig_buffer_size = (unsigned long long) max_bs * (unsigned long long) max_units; diff --git a/fio.h b/fio.h index e4ed76f..833a03b 100644 --- a/fio.h +++ b/fio.h @@ -181,6 +181,7 @@ struct thread_options { unsigned int verify_pattern_bytes; unsigned int verify_fatal; unsigned int verify_async; + unsigned int extra_buff_count; unsigned int use_thread; unsigned int unlink; unsigned int do_disk_util; diff --git a/options.c b/options.c index 5b88255..71f26fb 100644 --- a/options.c +++ b/options.c @@ -1337,6 +1337,13 @@ static struct fio_option options[] = { }, #endif { + .name = "extra_buff_count", + .type = FIO_OPT_INT, + .off1 = td_var_offset(extra_buff_count), + .def = "0", + .help = "Number of extra buffers to allocate", + }, + { .name = "write_iolog", .type = FIO_OPT_STR_STORE, .off1 = td_var_offset(write_iolog_file),