Recent changes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following changes since commit a5f3027cb0495dfe217b2626d248fcc054e7e878:

  Initial commit for TRIM/DISCARD support (2010-07-19 16:19:55 -0600)

are available in the git repository at:
  git://git.kernel.dk/fio.git master

Jens Axboe (2):
      Rename ddir_nr -> ddir_seq_nr
      Add rw_sequencer option

 HOWTO       |   27 ++++++++++++++---
 file.h      |    2 +
 filesetup.c |    2 +
 fio.1       |   34 +++++++++++++++++++--
 fio.h       |   13 +++++++-
 init.c      |    2 +-
 io_u.c      |   93 ++++++++++++++++++++++++++++++++++++++++++++++------------
 ioengine.h  |    1 +
 options.c   |   22 ++++++++++++-
 9 files changed, 163 insertions(+), 33 deletions(-)

---

Diff of recent changes:

diff --git a/HOWTO b/HOWTO
index bd5bebf..0ef7ca4 100644
--- a/HOWTO
+++ b/HOWTO
@@ -313,13 +313,30 @@ rw=str		Type of io pattern. Accepted values are:
 		For the mixed io types, the default is to split them 50/50.
 		For certain types of io the result may still be skewed a bit,
 		since the speed may be different. It is possible to specify
-		a number of IO's to do before getting a new offset - this
-		is only useful for random IO, where fio would normally
-		generate a new random offset for every IO. If you append
-		eg 8 to randread, you would get a new random offset for
+		a number of IO's to do before getting a new offset, this is
+		one by appending a ':<nr>' to the end of the string given.
+		For a random read, it would look like 'rw=randread:8' for
+		passing in an offset modifier with a value of 8. See the
+		'rw_sequencer' option.
+
+rw_sequencer=str If an offset modifier is given by appending a number to
+		the rw=<str> line, then this option controls how that
+		number modifies the IO offset being generated. Accepted
+		values are:
+
+			sequential	Generate sequential offset
+			identical	Generate the same offset
+
+		'sequential' is only useful for random IO, where fio would
+		normally generate a new random offset for every IO. If you
+		append eg 8 to randread, you would get a new random offset for
 		every 8 IO's. The result would be a seek for only every 8
 		IO's, instead of for every IO. Use rw=randread:8 to specify
-		that.
+		that. As sequential IO is already sequential, setting
+		'sequential' for that would not result in any differences.
+		'identical' behaves in a similar fashion, except it sends
+		the same offset 8 number of times before generating a new
+		offset.
 
 kb_base=int	The base unit for a kilobyte. The defacto base is 2^10, 1024.
 		Storage manufacturers like to use 10^3 or 1000 as a base
diff --git a/file.h b/file.h
index 30293fc..3b4ed0b 100644
--- a/file.h
+++ b/file.h
@@ -73,6 +73,7 @@ struct fio_file {
 	unsigned long long io_size;
 
 	unsigned long long last_pos;
+	unsigned long long last_start;
 
 	unsigned long long first_write;
 	unsigned long long last_write;
@@ -155,6 +156,7 @@ static inline void fio_file_reset(struct fio_file *f)
 {
 	f->last_free_lookup = 0;
 	f->last_pos = f->file_offset;
+	f->last_start = -1ULL;
 	f->file_pos = -1ULL;
 	if (f->file_map)
 		memset(f->file_map, 0, f->num_maps * sizeof(int));
diff --git a/filesetup.c b/filesetup.c
index f088390..d2b74d7 100644
--- a/filesetup.c
+++ b/filesetup.c
@@ -909,6 +909,7 @@ int add_file(struct thread_data *td, const char *fname)
 	}
 
 	f->fd = -1;
+	fio_file_reset(f);
 
 	if (td->files_size <= td->files_index) {
 		int new_size = td->o.nr_files + 1;
@@ -1136,6 +1137,7 @@ void dup_files(struct thread_data *td, struct thread_data *org)
 			assert(0);
 		}
 		__f->fd = -1;
+		fio_file_reset(__f);
 
 		if (f->file_name) {
 			__f->file_name = smalloc_strdup(f->file_name);
diff --git a/fio.1 b/fio.1
index 77773a0..c5c10af 100644
--- a/fio.1
+++ b/fio.1
@@ -172,11 +172,39 @@ Mixed sequential reads and writes.
 Mixed random reads and writes.
 .RE
 .P
-For mixed I/O, the default split is 50/50.  For random I/O, the number of I/Os
-to perform before getting a new offset can be specified by appending
-`:\fIint\fR' to the pattern type.  The default is 1.
+For mixed I/O, the default split is 50/50. For certain types of io the result
+may still be skewed a bit, since the speed may be different. It is possible to
+specify a number of IO's to do before getting a new offset, this is one by
+appending a `:\fI<nr>\fR to the end of the string given. For a random read, it
+would look like \fBrw=randread:8\fR for passing in an offset modifier with a
+value of 8. See the \fBrw_sequencer\fR option.
 .RE
 .TP
+.BI rw_sequencer \fR=\fPstr
+If an offset modifier is given by appending a number to the \fBrw=<str>\fR line,
+then this option controls how that number modifies the IO offset being
+generated. Accepted values are:
+.RS
+.RS
+.TP
+.B sequential
+Generate sequential offset
+.TP
+.B identical
+Generate the same offset
+.RE
+.P
+\fBsequential\fR is only useful for random IO, where fio would normally
+generate a new random offset for every IO. If you append eg 8 to randread, you
+would get a new random offset for every 8 IO's. The result would be a seek for
+only every 8 IO's, instead of for every IO. Use \fBrw=randread:8\fR to specify
+that. As sequential IO is already sequential, setting \fBsequential\fR for that
+would not result in any differences.  \fBidentical\fR behaves in a similar
+fashion, except it sends the same offset 8 number of times before generating a
+new offset.
+.RE
+.P
+.TP
 .BI kb_base \fR=\fPint
 The base unit for a kilobyte. The defacto base is 2^10, 1024.  Storage
 manufacturers like to use 10^3 or 1000 as a base ten unit instead, for obvious
diff --git a/fio.h b/fio.h
index e05d95a..de76e65 100644
--- a/fio.h
+++ b/fio.h
@@ -61,6 +61,14 @@ enum fio_memtype {
 };
 
 /*
+ * offset generator types
+ */
+enum {
+	RW_SEQ_SEQ	= 0,
+	RW_SEQ_IDENT,
+};
+
+/*
  * How many depth levels to log
  */
 #define FIO_IO_U_MAP_NR	8
@@ -145,8 +153,9 @@ struct thread_options {
 	char *opendir;
 	char *ioengine;
 	enum td_ddir td_ddir;
+	unsigned int rw_seq;
 	unsigned int kb_base;
-	unsigned int ddir_nr;
+	unsigned int ddir_seq_nr;
 	unsigned int iodepth;
 	unsigned int iodepth_low;
 	unsigned int iodepth_batch;
@@ -410,7 +419,7 @@ struct thread_data {
 	os_random_state_t rwmix_state;
 	unsigned long rwmix_issues;
 	enum fio_ddir rwmix_ddir;
-	unsigned int ddir_nr;
+	unsigned int ddir_seq_nr;
 
 	/*
 	 * IO history logs for verification. We use a tree for sorting,
diff --git a/init.c b/init.c
index bb645b0..09b9152 100644
--- a/init.c
+++ b/init.c
@@ -557,7 +557,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
 	td->ts.slat_stat[0].min_val = td->ts.slat_stat[1].min_val = ULONG_MAX;
 	td->ts.lat_stat[0].min_val = td->ts.lat_stat[1].min_val = ULONG_MAX;
 	td->ts.bw_stat[0].min_val = td->ts.bw_stat[1].min_val = ULONG_MAX;
-	td->ddir_nr = td->o.ddir_nr;
+	td->ddir_seq_nr = td->o.ddir_seq_nr + 1;
 
 	if ((td->o.stonewall || td->o.new_group) && prev_group_jobs) {
 		prev_group_jobs = 0;
diff --git a/io_u.c b/io_u.c
index f27cdda..3eeade2 100644
--- a/io_u.c
+++ b/io_u.c
@@ -41,10 +41,12 @@ static void mark_random_map(struct thread_data *td, struct io_u *io_u)
 	struct fio_file *f = io_u->file;
 	unsigned long long block;
 	unsigned int blocks, nr_blocks;
+	int busy_check;
 
 	block = (io_u->offset - f->file_offset) / (unsigned long long) min_bs;
 	nr_blocks = (io_u->buflen + min_bs - 1) / min_bs;
 	blocks = 0;
+	busy_check = !(io_u->flags & IO_U_F_BUSY_OK);
 
 	while (nr_blocks) {
 		unsigned int this_blocks, mask;
@@ -54,7 +56,11 @@ static void mark_random_map(struct thread_data *td, struct io_u *io_u)
 		 * If we have a mixed random workload, we may
 		 * encounter blocks we already did IO to.
 		 */
-		if ((td->o.ddir_nr == 1) && !random_map_free(f, block))
+		if (!busy_check) {
+			blocks = nr_blocks;
+			break;
+		}
+		if ((td->o.ddir_seq_nr == 1) && !random_map_free(f, block))
 			break;
 
 		idx = RAND_MAP_IDX(f, block);
@@ -190,6 +196,62 @@ static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
 	return get_next_free_block(td, f, ddir, b);
 }
 
+static int get_next_rand_block(struct thread_data *td, struct fio_file *f,
+			       enum fio_ddir ddir, unsigned long long *b)
+{
+	if (get_next_rand_offset(td, f, ddir, b)) {
+		dprint(FD_IO, "%s: rand offset failed, last=%llu, size=%llu\n",
+				f->file_name, f->last_pos, f->real_file_size);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int get_next_seq_block(struct thread_data *td, struct fio_file *f,
+			      enum fio_ddir ddir, unsigned long long *b)
+{
+	if (f->last_pos < f->real_file_size) {
+		*b = (f->last_pos - f->file_offset) / td->o.min_bs[ddir];
+		return 0;
+	}
+
+	return 1;
+}
+
+static int get_next_block(struct thread_data *td, struct io_u *io_u,
+			  enum fio_ddir ddir, int rw_seq, unsigned long long *b)
+{
+	struct fio_file *f = io_u->file;
+	int ret;
+
+	if (rw_seq) {
+		if (td_random(td))
+			ret = get_next_rand_block(td, f, ddir, b);
+		else
+			ret = get_next_seq_block(td, f, ddir, b);
+	} else {
+		io_u->flags |= IO_U_F_BUSY_OK;
+
+		if (td->o.rw_seq == RW_SEQ_SEQ) {
+			ret = get_next_seq_block(td, f, ddir, b);
+			if (ret)
+				ret = get_next_rand_block(td, f, ddir, b);
+		} else if (td->o.rw_seq == RW_SEQ_IDENT) {
+			if (f->last_start != -1ULL)
+				*b = (f->last_start - f->file_offset) / td->o.min_bs[ddir];
+			else
+				*b = 0;
+			ret = 0;
+		} else {
+			log_err("fio: unknown rw_seq=%d\n", td->o.rw_seq);
+			ret = 1;
+		}
+	}
+	
+	return ret;
+}
+
 /*
  * For random io, generate a random new block and see if it's used. Repeat
  * until we find a free one. For sequential io, just return the end of
@@ -200,26 +262,16 @@ static int __get_next_offset(struct thread_data *td, struct io_u *io_u)
 	struct fio_file *f = io_u->file;
 	unsigned long long b;
 	enum fio_ddir ddir = io_u->ddir;
+	int rw_seq_hit = 0;
 
-	if (td_random(td) && (td->o.ddir_nr && !--td->ddir_nr)) {
-		td->ddir_nr = td->o.ddir_nr;
+	if (td->o.ddir_seq_nr && !--td->ddir_seq_nr) {
+		rw_seq_hit = 1;
+		td->ddir_seq_nr = td->o.ddir_seq_nr;
+	}
 
-		if (get_next_rand_offset(td, f, ddir, &b)) {
-			dprint(FD_IO, "%s: getting rand offset failed\n",
-				f->file_name);
-			return 1;
-		}
-	} else {
-		if (f->last_pos >= f->real_file_size) {
-			if (!td_random(td) ||
-			     get_next_rand_offset(td, f, ddir, &b)) {
-				dprint(FD_IO, "%s: pos %llu > size %llu\n",
-						f->file_name, f->last_pos,
-						f->real_file_size);
-				return 1;
-			}
-		} else
-			b = (f->last_pos - f->file_offset) / td->o.min_bs[ddir];
+	if (get_next_block(td, io_u, ddir, rw_seq_hit, &b)) {
+		printf("fail\n");
+		return 1;
 	}
 
 	io_u->offset = b * td->o.ba[ddir];
@@ -977,6 +1029,7 @@ struct io_u *get_io_u(struct thread_data *td)
 			goto err_put;
 		}
 
+		f->last_start = io_u->offset;
 		f->last_pos = io_u->offset + io_u->buflen;
 
 		if (td->o.verify != VERIFY_NONE && io_u->ddir == DDIR_WRITE)
@@ -1042,7 +1095,7 @@ static void io_completed(struct thread_data *td, struct io_u *io_u,
 
 	td_io_u_lock(td);
 	assert(io_u->flags & IO_U_F_FLIGHT);
-	io_u->flags &= ~IO_U_F_FLIGHT;
+	io_u->flags &= ~(IO_U_F_FLIGHT | IO_U_F_BUSY_OK);
 	td_io_u_unlock(td);
 
 	if (ddir_sync(io_u->ddir)) {
diff --git a/ioengine.h b/ioengine.h
index ff3069b..389e95a 100644
--- a/ioengine.h
+++ b/ioengine.h
@@ -8,6 +8,7 @@ enum {
 	IO_U_F_FLIGHT		= 1 << 1,
 	IO_U_F_FREE_DEF		= 1 << 2,
 	IO_U_F_IN_CUR_DEPTH	= 1 << 3,
+	IO_U_F_BUSY_OK		= 1 << 4,
 };
 
 /*
diff --git a/options.c b/options.c
index 9230767..10e58db 100644
--- a/options.c
+++ b/options.c
@@ -203,9 +203,9 @@ static int str_rw_cb(void *data, const char *str)
 	struct thread_data *td = data;
 	char *nr = get_opt_postfix(str);
 
-	td->o.ddir_nr = 1;
+	td->o.ddir_seq_nr = 1;
 	if (nr) {
-		td->o.ddir_nr = atoi(nr);
+		td->o.ddir_seq_nr = atoi(nr);
 		free(nr);
 	}
 
@@ -882,6 +882,24 @@ static struct fio_option options[FIO_MAX_OPTS] = {
 		},
 	},
 	{
+		.name	= "rw_sequencer",
+		.type	= FIO_OPT_STR,
+		.off1	= td_var_offset(rw_seq),
+		.help	= "IO offset generator modifier",
+		.def	= "sequential",
+		.posval = {
+			  { .ival = "sequential",
+			    .oval = RW_SEQ_SEQ,
+			    .help = "Generate sequential offsets",
+			  },
+			  { .ival = "identical",
+			    .oval = RW_SEQ_IDENT,
+			    .help = "Generate identical offsets",
+			  },
+		},
+	},
+
+	{
 		.name	= "ioengine",
 		.type	= FIO_OPT_STR_STORE,
 		.off1	= td_var_offset(ioengine),
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux