Recent changes (master)

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

 



The following changes since commit 7c4d0fb7e9e038000978b43b5674f9ad049d36b9:

  Fix double free of td zone state index (2016-03-04 19:50:41 -0700)

are available in the git repository at:

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

for you to fetch changes up to de4096e8682a064ed9125af7ac30a3fe4021167b:

  rand: use bools (2016-03-07 15:38:44 -0700)

----------------------------------------------------------------
Andrey Kuzmin (1):
      io_u: speed up __get_next_buflen()

Jens Axboe (5):
      options: unify the bssplit/zone split code
      options: finish merge of bssplit/rand zone code
      options: improvements to parse dry run
      Add the sample JESD219 job file
      rand: use bools

 examples/jesd219.fio |  19 ++++
 io_u.c               |   2 +-
 lib/rand.c           |   4 +-
 lib/rand.h           |   5 +-
 options.c            | 267 ++++++++++++++++++++++++---------------------------
 5 files changed, 152 insertions(+), 145 deletions(-)
 create mode 100644 examples/jesd219.fio

---

Diff of recent changes:

diff --git a/examples/jesd219.fio b/examples/jesd219.fio
new file mode 100644
index 0000000..ab2c40e
--- /dev/null
+++ b/examples/jesd219.fio
@@ -0,0 +1,19 @@
+# Sample implementation of the JESD219 workload for SSD endurance
+# testing. It uses a specific distribution of block sizes and
+# read/write mix, as well as a specific distribution of where on
+# the device the IO accesses will land. Based on posting from
+# Jeff Furlong <jeff.furlong@xxxxxxxx>
+[JESD219]
+ioengine=libaio
+direct=1
+rw=randrw
+norandommap
+randrepeat=0
+rwmixread=40
+rwmixwrite=60
+iodepth=256
+numjobs=4
+bssplit=512/4:1024/1:1536/1:2048/1:2560/1:3072/1:3584/1:4k/67:8k/10:16k/7:32k/3:64k/3
+random_distribution=zoned:50/5:30/15:20/80
+filename=/dev/nvme0n1
+group_reporting=1
diff --git a/io_u.c b/io_u.c
index 0a39886..3299f29 100644
--- a/io_u.c
+++ b/io_u.c
@@ -553,7 +553,7 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
 
 				buflen = bsp->bs;
 				perc += bsp->perc;
-				if ((r <= ((frand_max / 100L) * perc)) &&
+				if ((r * 100UL <= frand_max * perc) &&
 				    io_u_fits(td, io_u, buflen))
 					break;
 			}
diff --git a/lib/rand.c b/lib/rand.c
index 1b661a8..9c3e0d6 100644
--- a/lib/rand.c
+++ b/lib/rand.c
@@ -76,7 +76,7 @@ static void __init_rand64(struct taus258_state *state, uint64_t seed)
 		__rand64(state);
 }
 
-void init_rand(struct frand_state *state, int use64)
+void init_rand(struct frand_state *state, bool use64)
 {
 	state->use64 = use64;
 
@@ -86,7 +86,7 @@ void init_rand(struct frand_state *state, int use64)
 		__init_rand64(&state->state64, 1);
 }
 
-void init_rand_seed(struct frand_state *state, unsigned int seed, int use64)
+void init_rand_seed(struct frand_state *state, unsigned int seed, bool use64)
 {
 	state->use64 = use64;
 
diff --git a/lib/rand.h b/lib/rand.h
index 49773b0..24fac23 100644
--- a/lib/rand.h
+++ b/lib/rand.h
@@ -2,6 +2,7 @@
 #define FIO_RAND_H
 
 #include <inttypes.h>
+#include "types.h"
 #include "../arch/arch.h"
 
 #define FRAND32_MAX	(-1U)
@@ -128,8 +129,8 @@ static inline int rand_between(struct frand_state *state, int start, int end)
 	return start + (int) ((double)end * (r / (rand_max(state) + 1.0)));
 }
 
-extern void init_rand(struct frand_state *, int);
-extern void init_rand_seed(struct frand_state *, unsigned int seed, int);
+extern void init_rand(struct frand_state *, bool);
+extern void init_rand_seed(struct frand_state *, unsigned int seed, bool);
 extern void __fill_random_buf(void *buf, unsigned int len, unsigned long seed);
 extern unsigned long fill_random_buf(struct frand_state *, void *buf, unsigned int len);
 extern void __fill_random_buf_percentage(unsigned long, void *, unsigned int, unsigned int, unsigned int, char *, unsigned int);
diff --git a/options.c b/options.c
index bc2d0ed..7075d84 100644
--- a/options.c
+++ b/options.c
@@ -44,35 +44,28 @@ static int bs_cmp(const void *p1, const void *p2)
 	return (int) bsp1->perc - (int) bsp2->perc;
 }
 
-static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
+struct split {
+	unsigned int nr;
+	unsigned int val1[100];
+	unsigned int val2[100];
+};
+
+static int split_parse_ddir(struct thread_options *o, struct split *split,
+			    enum fio_ddir ddir, char *str)
 {
-	struct bssplit *bssplit;
-	unsigned int i, perc, perc_missing;
-	unsigned int max_bs, min_bs;
+	unsigned int i, perc;
 	long long val;
 	char *fname;
 
-	o->bssplit_nr[ddir] = 4;
-	bssplit = malloc(4 * sizeof(struct bssplit));
+	split->nr = 0;
 
 	i = 0;
-	max_bs = 0;
-	min_bs = -1;
 	while ((fname = strsep(&str, ":")) != NULL) {
 		char *perc_str;
 
 		if (!strlen(fname))
 			break;
 
-		/*
-		 * grow struct buffer, if needed
-		 */
-		if (i == o->bssplit_nr[ddir]) {
-			o->bssplit_nr[ddir] <<= 1;
-			bssplit = realloc(bssplit, o->bssplit_nr[ddir]
-						  * sizeof(struct bssplit));
-		}
-
 		perc_str = strstr(fname, "/");
 		if (perc_str) {
 			*perc_str = '\0';
@@ -87,28 +80,53 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
 
 		if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
 			log_err("fio: bssplit conversion failed\n");
-			free(bssplit);
 			return 1;
 		}
 
-		if (val > max_bs)
-			max_bs = val;
-		if (val < min_bs)
-			min_bs = val;
-
-		bssplit[i].bs = val;
-		bssplit[i].perc = perc;
+		split->val1[i] = val;
+		split->val2[i] = perc;
 		i++;
+		if (i == 100)
+			break;
 	}
 
-	o->bssplit_nr[ddir] = i;
+	split->nr = i;
+	return 0;
+}
+
+static int bssplit_ddir(struct thread_options *o, enum fio_ddir ddir, char *str)
+{
+	unsigned int i, perc, perc_missing;
+	unsigned int max_bs, min_bs;
+	struct split split;
+
+	memset(&split, 0, sizeof(split));
+
+	if (split_parse_ddir(o, &split, ddir, str))
+		return 1;
+	if (!split.nr)
+		return 0;
+
+	max_bs = 0;
+	min_bs = -1;
+	o->bssplit[ddir] = malloc(split.nr * sizeof(struct bssplit));
+	o->bssplit_nr[ddir] = split.nr;
+	for (i = 0; i < split.nr; i++) {
+		if (split.val1[i] > max_bs)
+			max_bs = split.val1[i];
+		if (split.val1[i] < min_bs)
+			min_bs = split.val1[i];
+
+		o->bssplit[ddir][i].bs = split.val1[i];
+		o->bssplit[ddir][i].perc =split.val2[i];
+	}
 
 	/*
 	 * Now check if the percentages add up, and how much is missing
 	 */
 	perc = perc_missing = 0;
 	for (i = 0; i < o->bssplit_nr[ddir]; i++) {
-		struct bssplit *bsp = &bssplit[i];
+		struct bssplit *bsp = &o->bssplit[ddir][i];
 
 		if (bsp->perc == -1U)
 			perc_missing++;
@@ -118,7 +136,8 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
 
 	if (perc > 100 && perc_missing > 1) {
 		log_err("fio: bssplit percentages add to more than 100%%\n");
-		free(bssplit);
+		free(o->bssplit[ddir]);
+		o->bssplit[ddir] = NULL;
 		return 1;
 	}
 
@@ -130,7 +149,7 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
 		if (perc_missing == 1 && o->bssplit_nr[ddir] == 1)
 			perc = 100;
 		for (i = 0; i < o->bssplit_nr[ddir]; i++) {
-			struct bssplit *bsp = &bssplit[i];
+			struct bssplit *bsp = &o->bssplit[ddir][i];
 
 			if (bsp->perc == -1U)
 				bsp->perc = (100 - perc) / perc_missing;
@@ -143,60 +162,78 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
 	/*
 	 * now sort based on percentages, for ease of lookup
 	 */
-	qsort(bssplit, o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
-	o->bssplit[ddir] = bssplit;
+	qsort(o->bssplit[ddir], o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
 	return 0;
 }
 
-static int str_bssplit_cb(void *data, const char *input)
+typedef int (split_parse_fn)(struct thread_options *, enum fio_ddir, char *);
+
+static int str_split_parse(struct thread_data *td, char *str, split_parse_fn *fn)
 {
-	struct thread_data *td = data;
-	char *str, *p, *odir, *ddir;
+	char *odir, *ddir;
 	int ret = 0;
 
-	if (parse_dryrun())
-		return 0;
-
-	p = str = strdup(input);
-
-	strip_blank_front(&str);
-	strip_blank_end(str);
-
 	odir = strchr(str, ',');
 	if (odir) {
 		ddir = strchr(odir + 1, ',');
 		if (ddir) {
-			ret = bssplit_ddir(&td->o, DDIR_TRIM, ddir + 1);
+			ret = fn(&td->o, DDIR_TRIM, ddir + 1);
 			if (!ret)
 				*ddir = '\0';
 		} else {
 			char *op;
 
 			op = strdup(odir + 1);
-			ret = bssplit_ddir(&td->o, DDIR_TRIM, op);
+			ret = fn(&td->o, DDIR_TRIM, op);
 
 			free(op);
 		}
 		if (!ret)
-			ret = bssplit_ddir(&td->o, DDIR_WRITE, odir + 1);
+			ret = fn(&td->o, DDIR_WRITE, odir + 1);
 		if (!ret) {
 			*odir = '\0';
-			ret = bssplit_ddir(&td->o, DDIR_READ, str);
+			ret = fn(&td->o, DDIR_READ, str);
 		}
 	} else {
 		char *op;
 
 		op = strdup(str);
-		ret = bssplit_ddir(&td->o, DDIR_WRITE, op);
+		ret = fn(&td->o, DDIR_WRITE, op);
 		free(op);
 
 		if (!ret) {
 			op = strdup(str);
-			ret = bssplit_ddir(&td->o, DDIR_TRIM, op);
+			ret = fn(&td->o, DDIR_TRIM, op);
 			free(op);
 		}
 		if (!ret)
-			ret = bssplit_ddir(&td->o, DDIR_READ, str);
+			ret = fn(&td->o, DDIR_READ, str);
+	}
+
+	return ret;
+}
+
+static int str_bssplit_cb(void *data, const char *input)
+{
+	struct thread_data *td = data;
+	char *str, *p;
+	int ret = 0;
+
+	p = str = strdup(input);
+
+	strip_blank_front(&str);
+	strip_blank_end(str);
+
+	ret = str_split_parse(td, str, bssplit_ddir);
+
+	if (parse_dryrun()) {
+		int i;
+
+		for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+			free(td->o.bssplit[i]);
+			td->o.bssplit[i] = NULL;
+			td->o.bssplit_nr[i] = 0;
+		}
 	}
 
 	free(p);
@@ -714,64 +751,33 @@ static int zone_cmp(const void *p1, const void *p2)
 	return (int) zsp2->access_perc - (int) zsp1->access_perc;
 }
 
-static int zone_split_ddir(struct thread_options *o, int ddir, char *str)
+static int zone_split_ddir(struct thread_options *o, enum fio_ddir ddir,
+			   char *str)
 {
-	struct zone_split *zsplit;
 	unsigned int i, perc, perc_missing, sperc, sperc_missing;
-	long long val;
-	char *fname;
+	struct split split;
 
-	o->zone_split_nr[ddir] = 4;
-	zsplit = malloc(4 * sizeof(struct zone_split));
-
-	i = 0;
-	while ((fname = strsep(&str, ":")) != NULL) {
-		char *perc_str;
+	memset(&split, 0, sizeof(split));
 
-		if (!strlen(fname))
-			break;
-
-		/*
-		 * grow struct buffer, if needed
-		 */
-		if (i == o->zone_split_nr[ddir]) {
-			o->zone_split_nr[ddir] <<= 1;
-			zsplit = realloc(zsplit, o->zone_split_nr[ddir]
-						  * sizeof(struct zone_split));
-		}
-
-		perc_str = strstr(fname, "/");
-		if (perc_str) {
-			*perc_str = '\0';
-			perc_str++;
-			perc = atoi(perc_str);
-			if (perc > 100)
-				perc = 100;
-			else if (!perc)
-				perc = -1U;
-		} else
-			perc = -1U;
-
-		if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
-			log_err("fio: zone_split conversion failed\n");
-			free(zsplit);
-			return 1;
-		}
+	if (split_parse_ddir(o, &split, ddir, str))
+		return 1;
+	if (!split.nr)
+		return 0;
 
-		zsplit[i].access_perc = val;
-		zsplit[i].size_perc = perc;
-		i++;
+	o->zone_split[ddir] = malloc(split.nr * sizeof(struct zone_split));
+	o->zone_split_nr[ddir] = split.nr;
+	for (i = 0; i < split.nr; i++) {
+		o->zone_split[ddir][i].access_perc = split.val1[i];
+		o->zone_split[ddir][i].size_perc = split.val2[i];
 	}
 
-	o->zone_split_nr[ddir] = i;
-
 	/*
 	 * Now check if the percentages add up, and how much is missing
 	 */
 	perc = perc_missing = 0;
 	sperc = sperc_missing = 0;
 	for (i = 0; i < o->zone_split_nr[ddir]; i++) {
-		struct zone_split *zsp = &zsplit[i];
+		struct zone_split *zsp = &o->zone_split[ddir][i];
 
 		if (zsp->access_perc == (uint8_t) -1U)
 			perc_missing++;
@@ -787,13 +793,15 @@ static int zone_split_ddir(struct thread_options *o, int ddir, char *str)
 
 	if (perc > 100 || sperc > 100) {
 		log_err("fio: zone_split percentages add to more than 100%%\n");
-		free(zsplit);
+		free(o->zone_split[ddir]);
+		o->zone_split[ddir] = NULL;
 		return 1;
 	}
 	if (perc < 100) {
 		log_err("fio: access percentage don't add up to 100 for zoned "
 			"random distribution (got=%u)\n", perc);
-		free(zsplit);
+		free(o->zone_split[ddir]);
+		o->zone_split[ddir] = NULL;
 		return 1;
 	}
 
@@ -805,7 +813,7 @@ static int zone_split_ddir(struct thread_options *o, int ddir, char *str)
 		if (perc_missing == 1 && o->zone_split_nr[ddir] == 1)
 			perc = 100;
 		for (i = 0; i < o->zone_split_nr[ddir]; i++) {
-			struct zone_split *zsp = &zsplit[i];
+			struct zone_split *zsp = &o->zone_split[ddir][i];
 
 			if (zsp->access_perc == (uint8_t) -1U)
 				zsp->access_perc = (100 - perc) / perc_missing;
@@ -815,7 +823,7 @@ static int zone_split_ddir(struct thread_options *o, int ddir, char *str)
 		if (sperc_missing == 1 && o->zone_split_nr[ddir] == 1)
 			sperc = 100;
 		for (i = 0; i < o->zone_split_nr[ddir]; i++) {
-			struct zone_split *zsp = &zsplit[i];
+			struct zone_split *zsp = &o->zone_split[ddir][i];
 
 			if (zsp->size_perc == (uint8_t) -1U)
 				zsp->size_perc = (100 - sperc) / sperc_missing;
@@ -825,8 +833,7 @@ static int zone_split_ddir(struct thread_options *o, int ddir, char *str)
 	/*
 	 * now sort based on percentages, for ease of lookup
 	 */
-	qsort(zsplit, o->zone_split_nr[ddir], sizeof(struct zone_split), zone_cmp);
-	o->zone_split[ddir] = zsplit;
+	qsort(o->zone_split[ddir], o->zone_split_nr[ddir], sizeof(struct zone_split), zone_cmp);
 	return 0;
 }
 
@@ -869,7 +876,7 @@ static void td_zone_gen_index(struct thread_data *td)
 
 static int parse_zoned_distribution(struct thread_data *td, const char *input)
 {
-	char *str, *p, *odir, *ddir;
+	char *str, *p;
 	int i, ret = 0;
 
 	p = str = strdup(input);
@@ -885,42 +892,7 @@ static int parse_zoned_distribution(struct thread_data *td, const char *input)
 	}
 	str += strlen("zoned:");
 
-	odir = strchr(str, ',');
-	if (odir) {
-		ddir = strchr(odir + 1, ',');
-		if (ddir) {
-			ret = zone_split_ddir(&td->o, DDIR_TRIM, ddir + 1);
-			if (!ret)
-				*ddir = '\0';
-		} else {
-			char *op;
-
-			op = strdup(odir + 1);
-			ret = zone_split_ddir(&td->o, DDIR_TRIM, op);
-
-			free(op);
-		}
-		if (!ret)
-			ret = zone_split_ddir(&td->o, DDIR_WRITE, odir + 1);
-		if (!ret) {
-			*odir = '\0';
-			ret = zone_split_ddir(&td->o, DDIR_READ, str);
-		}
-	} else {
-		char *op;
-
-		op = strdup(str);
-		ret = zone_split_ddir(&td->o, DDIR_WRITE, op);
-		free(op);
-
-		if (!ret) {
-			op = strdup(str);
-			ret = zone_split_ddir(&td->o, DDIR_TRIM, op);
-			free(op);
-		}
-		if (!ret)
-			ret = zone_split_ddir(&td->o, DDIR_READ, str);
-	}
+	ret = str_split_parse(td, str, zone_split_ddir);
 
 	free(p);
 
@@ -937,6 +909,18 @@ static int parse_zoned_distribution(struct thread_data *td, const char *input)
 		}
 	}
 
+	if (parse_dryrun()) {
+		int i;
+
+		for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+			free(td->o.zone_split[i]);
+			td->o.zone_split[i] = NULL;
+			td->o.zone_split_nr[i] = 0;
+		}
+
+		return ret;
+	}
+
 	if (!ret)
 		td_zone_gen_index(td);
 	else {
@@ -953,9 +937,6 @@ static int str_random_distribution_cb(void *data, const char *str)
 	double val;
 	char *nr;
 
-	if (parse_dryrun())
-		return 0;
-
 	if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
 		val = FIO_DEF_ZIPF;
 	else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
@@ -981,18 +962,24 @@ static int str_random_distribution_cb(void *data, const char *str)
 			log_err("fio: zipf theta must different than 1.0\n");
 			return 1;
 		}
+		if (parse_dryrun())
+			return 0;
 		td->o.zipf_theta.u.f = val;
 	} else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) {
 		if (val <= 0.00 || val >= 1.00) {
 			log_err("fio: pareto input out of range (0 < input < 1.0)\n");
 			return 1;
 		}
+		if (parse_dryrun())
+			return 0;
 		td->o.pareto_h.u.f = val;
 	} else {
 		if (val <= 0.00 || val >= 100.0) {
 			log_err("fio: normal deviation out of range (0 < input < 100.0)\n");
 			return 1;
 		}
+		if (parse_dryrun())
+			return 0;
 		td->o.gauss_dev.u.f = val;
 	}
 
--
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