Add low water mark for queuing depth

Current fio will attempt to keep the queue full at all times,
but sometimes that's not what you want. Add iodepth_low to
indicate a low water mark for queuing depth, so that when we
see a FIO_Q_BUSY or run out of free requests, let the queue
drain down to the iodepth_low setting before building it up
again.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/HOWTO b/HOWTO
index ac15fc8..ea98810 100644
--- a/HOWTO
+++ b/HOWTO
@@ -294,6 +294,13 @@
 		job, can be overridden with a larger value for higher
 		concurrency.
 
+iodepth_low=int	The low water mark indicating when to start filling
+		the queue again. Defaults to the same as iodepth, meaning
+		that fio will attempt to keep the queue full at all times.
+		If iodepth is set to eg 16 and iodepth_low is set to 4, then
+		after fio has filled the queue of 16 requests, it will let
+		the depth drain down to 4 before starting to fill it again.
+
 direct=bool	If value is true, use non-buffered io. This is usually
 		O_DIRECT.
 
diff --git a/fio.c b/fio.c
index e4fec4f..1c2748e 100644
--- a/fio.c
+++ b/fio.c
@@ -287,9 +287,13 @@
 		 * completed io_u's first.
 		 */
 		min_events = 0;
-		if (queue_full(td) || ret == FIO_Q_BUSY)
+		if (queue_full(td) || ret == FIO_Q_BUSY) {
 			min_events = 1;
 
+			if (td->cur_depth > td->iodepth_low)
+				min_events = td->cur_depth - td->iodepth_low;
+		}
+
 		/*
 		 * Reap required number of io units, if any, and do the
 		 * verification on them through the callback handler
@@ -411,9 +415,13 @@
 		 */
 		if (ret == FIO_Q_QUEUED || ret == FIO_Q_BUSY) {
 			min_evts = 0;
-			if (queue_full(td) || ret == FIO_Q_BUSY)
+			if (queue_full(td) || ret == FIO_Q_BUSY) {
 				min_evts = 1;
 
+				if (td->cur_depth > td->iodepth_low)
+					min_evts = td->cur_depth - td->iodepth_low;
+			}
+
 			fio_gettime(&comp_time, NULL);
 			bytes_done = io_u_queued_complete(td, min_evts, NULL);
 			if (bytes_done < 0)
diff --git a/fio.h b/fio.h
index 38de5e3..282ccf0 100644
--- a/fio.h
+++ b/fio.h
@@ -325,6 +325,7 @@
 	unsigned int stonewall;
 	unsigned int numjobs;
 	unsigned int iodepth;
+	unsigned int iodepth_low;
 	os_cpu_mask_t cpumask;
 	unsigned int iolog;
 	unsigned int read_iolog;
diff --git a/init.c b/init.c
index 6dc221e..5630c9f 100644
--- a/init.c
+++ b/init.c
@@ -91,6 +91,12 @@
 		.def	= "1",
 	},
 	{
+		.name	= "iodepth_low",
+		.type	= FIO_OPT_INT,
+		.off1	= td_var_offset(iodepth_low),
+		.help	= "Low water mark for queuing depth",
+	},
+	{
 		.name	= "size",
 		.type	= FIO_OPT_STR_VAL,
 		.off1	= td_var_offset(total_file_size),
@@ -644,6 +650,14 @@
 	 */
 	if (td->thinktime_spin > td->thinktime)
 		td->thinktime_spin = td->thinktime;
+
+	/*
+	 * The low water mark cannot be bigger than the iodepth
+	 */
+	if (td->iodepth_low > td->iodepth || !td->iodepth_low)
+		td->iodepth_low = td->iodepth;
+
+	printf("io depth %d/%d\n", td->iodepth_low, td->iodepth);
 }
 
 /*