[PATCH] Add 'bs_unaligned' option

If this is specified with 'bsrange', fio will use any byte size value
in the bs range for an io unit buffer length. Normally fio defaults to
using a multiple of the minimum bs size, as that is required for any
type of raw io.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/HOWTO b/HOWTO
index 6d215ac..79d31df 100644
--- a/HOWTO
+++ b/HOWTO
@@ -223,7 +223,11 @@
 bsrange=irange	Instead of giving a single block size, specify a range
 		and fio will mix the issued io block sizes. The issued
 		io unit will always be a multiple of the minimum value
-		given.
+		given (also see bs_unaligned).
+
+bs_unaligned	If this option is given, any byte size value within bsrange
+		may be used as a block range. This typically wont work with
+		direct IO, as that normally requires sector alignment.
 
 nrfiles=int	Number of files to use for this job. Defaults to 1.
 
diff --git a/fio.h b/fio.h
index b48ef70..b30dec5 100644
--- a/fio.h
+++ b/fio.h
@@ -203,6 +203,7 @@
 	unsigned int write_lat_log;
 	unsigned int write_bw_log;
 	unsigned int norandommap;
+	unsigned int bs_unaligned;
 
 	unsigned int bs;
 	unsigned int min_bs;
diff --git a/init.c b/init.c
index e4f866a..6ad3c64 100644
--- a/init.c
+++ b/init.c
@@ -349,6 +349,11 @@
 		.off1	= td_var_offset(norandommap),
 	},
 	{
+		.name	= "bs_unaligned",
+		.type	= FIO_OPT_STR_SET,
+		.off1	= td_var_offset(bs_unaligned),
+	},
+	{
 		.name = NULL,
 	},
 };
@@ -490,6 +495,8 @@
 		log_err("fio: norandommap given, verify disabled\n");
 		td->verify = VERIFY_NONE;
 	}
+	if (td->bs_unaligned && (td->odirect || td->io_ops->flags & FIO_RAWIO))
+		log_err("fio: bs_unaligned may not work with raw io\n");
 }
 
 /*
@@ -535,6 +542,9 @@
 		}
 	}
 
+	if (td->odirect)
+		td->io_ops->flags |= FIO_RAWIO;
+
 	fixup_options(td);
 
 	td->filetype = FIO_TYPE_FILE;
@@ -545,9 +555,6 @@
 			td->filetype = FIO_TYPE_CHAR;
 	}
 
-	if (td->odirect)
-		td->io_ops->flags |= FIO_RAWIO;
-
 	if (td->filename)
 		td->nr_uniq_files = 1;
 	else
diff --git a/io_u.c b/io_u.c
index 0432079..3000ea7 100644
--- a/io_u.c
+++ b/io_u.c
@@ -121,7 +121,8 @@
 	else {
 		r = os_random_long(&td->bsrange_state);
 		buflen = (1 + (double) (td->max_bs - 1) * r / (RAND_MAX + 1.0));
-		buflen = (buflen + td->min_bs - 1) & ~(td->min_bs - 1);
+		if (!td->bs_unaligned)
+			buflen = (buflen + td->min_bs - 1) & ~(td->min_bs - 1);
 	}
 
 	if (buflen > td->io_size - td->this_io_bytes[td->ddir]) {