Recent changes (master)

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

 



The following changes since commit 68d96e515825185b232bbc8d2e5b5136b90514be:

  treat error in addr conversion to string as non-fatal (2015-05-26 15:12:46 -0400)

are available in the git repository at:

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

for you to fetch changes up to 37fbd7e9dd4f041b858507b3db06753614083770:

  filesetup: print warning if chosen random generator can't cover range (2015-05-29 19:40:21 -0600)

----------------------------------------------------------------
Jens Axboe (3):
      Add Intel rdrand support
      rand: add 64-bit tausworthe variant with a 2^258 cycle
      filesetup: print warning if chosen random generator can't cover range

 HOWTO                  |  2 +
 arch/arch-x86-common.h | 33 ++++++++++-------
 arch/arch-x86_64.h     | 30 +++++++++++++++
 backend.c              |  5 ++-
 crc/test.c             |  2 +-
 filesetup.c            | 14 ++++++-
 fio.1                  |  3 ++
 fio.h                  |  1 +
 init.c                 | 41 +++++++++++++--------
 io_u.c                 | 31 +++++++++++-----
 lib/gauss.c            |  4 +-
 lib/rand.c             | 42 +++++++++++++++++----
 lib/rand.h             | 92 ++++++++++++++++++++++++++++++++++++++++++----
 lib/zipf.c             |  6 +--
 options.c              |  5 +++
 server.c               |  4 +-
 server.h               |  2 +-
 trim.c                 |  4 +-
 verify.c               | 99 +++++++++++++++++++++++++++++++++++++++++---------
 verify.h               | 39 +++++++++++++++++---
 20 files changed, 369 insertions(+), 90 deletions(-)

---

Diff of recent changes:

diff --git a/HOWTO b/HOWTO
index ab0250c..291327d 100644
--- a/HOWTO
+++ b/HOWTO
@@ -961,6 +961,8 @@ random_generator=str	Fio supports the following engines for generating
 
 		tausworthe	Strong 2^88 cycle random number generator
 		lfsr		Linear feedback shift register generator
+		tausworthe64	Strong 64-bit 2^258 cycle random number
+				generator
 
 		Tausworthe is a strong random number generator, but it
 		requires tracking on the side if we want to ensure that
diff --git a/arch/arch-x86-common.h b/arch/arch-x86-common.h
index 31aa79f..cbf66b8 100644
--- a/arch/arch-x86-common.h
+++ b/arch/arch-x86-common.h
@@ -15,8 +15,9 @@ static inline void cpuid(unsigned int op,
 #define ARCH_HAVE_INIT
 
 extern int tsc_reliable;
+extern int arch_random;
 
-static inline int arch_init_intel(unsigned int level)
+static inline void arch_init_intel(unsigned int level)
 {
 	unsigned int eax, ebx, ecx = 0, edx;
 
@@ -26,47 +27,51 @@ static inline int arch_init_intel(unsigned int level)
 	eax = 1;
 	do_cpuid(&eax, &ebx, &ecx, &edx);
 	if (!(edx & (1U << 4)))
-		return 0;
+		return;
 
 	/*
 	 * Check for constant rate and synced (across cores) TSC
 	 */
 	eax = 0x80000007;
 	do_cpuid(&eax, &ebx, &ecx, &edx);
-	return edx & (1U << 8);
+	tsc_reliable = (edx & (1U << 8)) != 0;
+
+	/*
+	 * Check for FDRAND
+	 */
+	eax = 0x1;
+	do_cpuid(&eax, &ebx, &ecx, &edx);
+	arch_random = (ecx & (1U << 30)) != 0;
 }
 
-static inline int arch_init_amd(unsigned int level)
+static inline void arch_init_amd(unsigned int level)
 {
 	unsigned int eax, ebx, ecx, edx;
 
 	cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
 	if (eax < 0x80000007)
-		return 0;
+		return;
 
 	cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
-	if (edx & (1 << 8))
-		return 1;
-
-	return 0;
+	tsc_reliable = (edx & (1U << 8)) != 0;
 }
 
-static inline int arch_init(char *envp[])
+static inline void arch_init(char *envp[])
 {
 	unsigned int level;
 	char str[13];
 
+	arch_random = tsc_reliable = 0;
+
 	cpuid(0, &level, (unsigned int *) &str[0],
 			 (unsigned int *) &str[8],
 			 (unsigned int *) &str[4]);
 
 	str[12] = '\0';
 	if (!strcmp(str, "GenuineIntel"))
-		tsc_reliable = arch_init_intel(level);
+		arch_init_intel(level);
 	else if (!strcmp(str, "AuthenticAMD"))
-		tsc_reliable = arch_init_amd(level);
-
-	return 0;
+		arch_init_amd(level);
 }
 
 #endif
diff --git a/arch/arch-x86_64.h b/arch/arch-x86_64.h
index 61ac75e..8f33fc5 100644
--- a/arch/arch-x86_64.h
+++ b/arch/arch-x86_64.h
@@ -60,4 +60,34 @@ static inline unsigned long long get_cpu_clock(void)
 #define ARCH_HAVE_SSE4_2
 #define ARCH_HAVE_CPU_CLOCK
 
+#define RDRAND_LONG	".byte 0x48,0x0f,0xc7,0xf0"
+#define RDSEED_LONG	".byte 0x48,0x0f,0xc7,0xf8"
+#define RDRAND_RETRY	100
+
+static inline int arch_rand_long(unsigned long *val)
+{
+	int ok;
+
+	asm volatile("1: " RDRAND_LONG "\n\t"
+		     "jc 2f\n\t"
+		     "decl %0\n\t"
+		     "jnz 1b\n\t"
+		     "2:"
+		     : "=r" (ok), "=a" (*val)
+		     : "0" (RDRAND_RETRY));
+
+	return ok;
+}
+
+static inline int arch_rand_seed(unsigned long *seed)
+{
+	unsigned char ok;
+
+	asm volatile(RDSEED_LONG "\n\t"
+			"setc %0"
+			: "=qm" (ok), "=a" (*seed));
+
+	return 0;
+}
+
 #endif
diff --git a/backend.c b/backend.c
index ef5003e..2aa8840 100644
--- a/backend.c
+++ b/backend.c
@@ -1878,11 +1878,12 @@ static int fio_verify_load_state(struct thread_data *td)
 
 	if (is_backend) {
 		void *data;
+		int ver;
 
 		ret = fio_server_get_verify_state(td->o.name,
-					td->thread_number - 1, &data);
+					td->thread_number - 1, &data, &ver);
 		if (!ret)
-			verify_convert_assign_state(td, data);
+			verify_convert_assign_state(td, data, ver);
 	} else
 		ret = verify_load_state(td, "local");
 
diff --git a/crc/test.c b/crc/test.c
index dbc5653..05ea73e 100644
--- a/crc/test.c
+++ b/crc/test.c
@@ -306,7 +306,7 @@ int fio_crctest(const char *type)
 	}
 
 	buf = malloc(CHUNK);
-	init_rand_seed(&state, 0x8989);
+	init_rand_seed(&state, 0x8989, 0);
 	fill_random_buf(&state, buf, CHUNK);
 
 	for (i = 0; t[i].name; i++) {
diff --git a/filesetup.c b/filesetup.c
index cf8ae94..51efdf7 100644
--- a/filesetup.c
+++ b/filesetup.c
@@ -267,11 +267,13 @@ error:
 static unsigned long long get_rand_file_size(struct thread_data *td)
 {
 	unsigned long long ret, sized;
+	uint64_t frand_max;
 	unsigned long r;
 
+	frand_max = rand_max(&td->file_size_state);
 	r = __rand(&td->file_size_state);
 	sized = td->o.file_size_high - td->o.file_size_low;
-	ret = (unsigned long long) ((double) sized * (r / (FRAND_MAX + 1.0)));
+	ret = (unsigned long long) ((double) sized * (r / (frand_max + 1.0)));
 	ret += td->o.file_size_low;
 	ret -= (ret % td->o.rw_min_bs);
 	return ret;
@@ -1065,6 +1067,16 @@ int init_random_map(struct thread_data *td)
 
 		blocks = fsize / (unsigned long long) td->o.rw_min_bs;
 
+		if (blocks > FRAND32_MAX &&
+		    td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE &&
+		    !fio_option_is_set(&td->o, random_generator)) {
+			log_err("fio: file %s exceeds 32-bit tausworthe "
+				 "random generator. Use lfsr or "
+				 "tausworthe64.\n", f->file_name);
+			td_verror(td, EINVAL, "init file random");
+			return 1;
+		}
+
 		if (td->o.random_generator == FIO_RAND_GEN_LFSR) {
 			unsigned long seed;
 
diff --git a/fio.1 b/fio.1
index 36f80d6..1657082 100644
--- a/fio.1
+++ b/fio.1
@@ -843,6 +843,9 @@ Strong 2^88 cycle random number generator
 .B lfsr
 Linear feedback shift register generator
 .TP
+.B tausworthe64
+Strong 64-bit 2^258 cycle random number generator
+.TP
 .RE
 .P
 Tausworthe is a strong random number generator, but it requires tracking on the
diff --git a/fio.h b/fio.h
index 6659e28..4e2532f 100644
--- a/fio.h
+++ b/fio.h
@@ -686,6 +686,7 @@ enum {
 enum {
 	FIO_RAND_GEN_TAUSWORTHE = 0,
 	FIO_RAND_GEN_LFSR,
+	FIO_RAND_GEN_TAUSWORTHE64,
 };
 
 enum {
diff --git a/init.c b/init.c
index f34e818..9f1041c 100644
--- a/init.c
+++ b/init.c
@@ -496,12 +496,14 @@ static int fixed_block_size(struct thread_options *o)
 static unsigned long long get_rand_start_delay(struct thread_data *td)
 {
 	unsigned long long delayrange;
+	uint64_t frand_max;
 	unsigned long r;
 
 	delayrange = td->o.start_delay_high - td->o.start_delay;
 
+	frand_max = rand_max(&td->delay_state);
 	r = __rand(&td->delay_state);
-	delayrange = (unsigned long long) ((double) delayrange * (r / (FRAND_MAX + 1.0)));
+	delayrange = (unsigned long long) ((double) delayrange * (r / (frand_max + 1.0)));
 
 	delayrange += td->o.start_delay;
 	return delayrange;
@@ -827,18 +829,18 @@ static int exists_and_not_file(const char *filename)
 	return 1;
 }
 
-static void td_fill_rand_seeds_internal(struct thread_data *td)
+static void td_fill_rand_seeds_internal(struct thread_data *td, int use64)
 {
-	init_rand_seed(&td->bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF]);
-	init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF]);
-	init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF]);
+	init_rand_seed(&td->bsrange_state, td->rand_seeds[FIO_RAND_BS_OFF], use64);
+	init_rand_seed(&td->verify_state, td->rand_seeds[FIO_RAND_VER_OFF], use64);
+	init_rand_seed(&td->rwmix_state, td->rand_seeds[FIO_RAND_MIX_OFF], use64);
 
 	if (td->o.file_service_type == FIO_FSERVICE_RANDOM)
-		init_rand_seed(&td->next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF]);
+		init_rand_seed(&td->next_file_state, td->rand_seeds[FIO_RAND_FILE_OFF], use64);
 
-	init_rand_seed(&td->file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF]);
-	init_rand_seed(&td->trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF]);
-	init_rand_seed(&td->delay_state, td->rand_seeds[FIO_RAND_START_DELAY]);
+	init_rand_seed(&td->file_size_state, td->rand_seeds[FIO_RAND_FILE_SIZE_OFF], use64);
+	init_rand_seed(&td->trim_state, td->rand_seeds[FIO_RAND_TRIM_OFF], use64);
+	init_rand_seed(&td->delay_state, td->rand_seeds[FIO_RAND_START_DELAY], use64);
 
 	if (!td_random(td))
 		return;
@@ -846,14 +848,16 @@ static void td_fill_rand_seeds_internal(struct thread_data *td)
 	if (td->o.rand_repeatable)
 		td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number;
 
-	init_rand_seed(&td->random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF]);
-	init_rand_seed(&td->seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF]);
-	init_rand_seed(&td->seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF]);
-	init_rand_seed(&td->seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF]);
+	init_rand_seed(&td->random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF], use64);
+	init_rand_seed(&td->seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], use64);
+	init_rand_seed(&td->seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF], use64);
+	init_rand_seed(&td->seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF], use64);
 }
 
 void td_fill_rand_seeds(struct thread_data *td)
 {
+	int use64;
+
 	if (td->o.allrand_repeatable) {
 		unsigned int i;
 
@@ -862,12 +866,17 @@ void td_fill_rand_seeds(struct thread_data *td)
 			       	+ i;
 	}
 
-	td_fill_rand_seeds_internal(td);
+	if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64)
+		use64 = 1;
+	else
+		use64 = 0;
+
+	td_fill_rand_seeds_internal(td, use64);
 
-	init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF]);
+	init_rand_seed(&td->buf_state, td->rand_seeds[FIO_RAND_BUF_OFF], use64);
 	frand_copy(&td->buf_state_prev, &td->buf_state);
 
-	init_rand_seed(&td->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF]);
+	init_rand_seed(&td->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF], use64);
 }
 
 /*
diff --git a/io_u.c b/io_u.c
index e67149d..63a176f 100644
--- a/io_u.c
+++ b/io_u.c
@@ -89,18 +89,20 @@ static int __get_next_rand_offset(struct thread_data *td, struct fio_file *f,
 {
 	uint64_t r;
 
-	if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE) {
-		uint64_t lastb;
+	if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE ||
+	    td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64) {
+		uint64_t frand_max, lastb;
 
 		lastb = last_block(td, f, ddir);
 		if (!lastb)
 			return 1;
 
+		frand_max = rand_max(&td->random_state);
 		r = __rand(&td->random_state);
 
 		dprint(FD_RANDOM, "off rand %llu\n", (unsigned long long) r);
 
-		*b = lastb * (r / ((uint64_t) FRAND_MAX + 1.0));
+		*b = lastb * (r / ((uint64_t) frand_max + 1.0));
 	} else {
 		uint64_t off = 0;
 
@@ -195,7 +197,8 @@ static inline int should_sort_io(struct thread_data *td)
 		return 0;
 	if (td->runstate != TD_VERIFYING)
 		return 0;
-	if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE)
+	if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE ||
+	    td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE64)
 		return 0;
 
 	return 1;
@@ -203,14 +206,16 @@ static inline int should_sort_io(struct thread_data *td)
 
 static int should_do_random(struct thread_data *td, enum fio_ddir ddir)
 {
+	uint64_t frand_max;
 	unsigned int v;
 	unsigned long r;
 
 	if (td->o.perc_rand[ddir] == 100)
 		return 1;
 
+	frand_max = rand_max(&td->seq_rand_state[ddir]);
 	r = __rand(&td->seq_rand_state[ddir]);
-	v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0)));
+	v = 1 + (int) (100.0 * (r / (frand_max + 1.0)));
 
 	return v <= td->o.perc_rand[ddir];
 }
@@ -439,6 +444,7 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
 	int ddir = io_u->ddir;
 	unsigned int buflen = 0;
 	unsigned int minbs, maxbs;
+	uint64_t frand_max;
 	unsigned long r;
 
 	assert(ddir_rw(ddir));
@@ -458,12 +464,13 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
 	if (!io_u_fits(td, io_u, minbs))
 		return 0;
 
+	frand_max = rand_max(&td->bsrange_state);
 	do {
 		r = __rand(&td->bsrange_state);
 
 		if (!td->o.bssplit_nr[ddir]) {
 			buflen = 1 + (unsigned int) ((double) maxbs *
-					(r / (FRAND_MAX + 1.0)));
+					(r / (frand_max + 1.0)));
 			if (buflen < minbs)
 				buflen = minbs;
 		} else {
@@ -475,7 +482,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 <= ((frand_max / 100L) * perc)) &&
 				    io_u_fits(td, io_u, buflen))
 					break;
 			}
@@ -521,11 +528,12 @@ static void set_rwmix_bytes(struct thread_data *td)
 
 static inline enum fio_ddir get_rand_ddir(struct thread_data *td)
 {
+	uint64_t frand_max = rand_max(&td->rwmix_state);
 	unsigned int v;
 	unsigned long r;
 
 	r = __rand(&td->rwmix_state);
-	v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0)));
+	v = 1 + (int) (100.0 * (r / (frand_max + 1.0)));
 
 	if (v <= td->o.rwmix[DDIR_READ])
 		return DDIR_READ;
@@ -992,6 +1000,7 @@ static struct fio_file *get_next_file_rand(struct thread_data *td,
 					   enum fio_file_flags goodf,
 					   enum fio_file_flags badf)
 {
+	uint64_t frand_max = rand_max(&td->next_file_state);
 	struct fio_file *f;
 	int fno;
 
@@ -1001,7 +1010,7 @@ static struct fio_file *get_next_file_rand(struct thread_data *td,
 
 		r = __rand(&td->next_file_state);
 		fno = (unsigned int) ((double) td->o.nr_files
-				* (r / (FRAND_MAX + 1.0)));
+				* (r / (frand_max + 1.0)));
 
 		f = td->files[fno];
 		if (fio_file_done(f))
@@ -1892,6 +1901,7 @@ void io_u_queued(struct thread_data *td, struct io_u *io_u)
  */
 static struct frand_state *get_buf_state(struct thread_data *td)
 {
+	uint64_t frand_max;
 	unsigned int v;
 	unsigned long r;
 
@@ -1902,8 +1912,9 @@ static struct frand_state *get_buf_state(struct thread_data *td)
 		return &td->buf_state;
 	}
 
+	frand_max = rand_max(&td->dedupe_state);
 	r = __rand(&td->dedupe_state);
-	v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0)));
+	v = 1 + (int) (100.0 * (r / (frand_max + 1.0)));
 
 	if (v <= td->o.dedupe_percentage)
 		return &td->buf_state_prev;
diff --git a/lib/gauss.c b/lib/gauss.c
index 1bb6c41..afd0490 100644
--- a/lib/gauss.c
+++ b/lib/gauss.c
@@ -15,7 +15,7 @@ static int gauss_dev(struct gauss_state *gs)
 		return 0;
 
 	r = __rand(&gs->r);
-	vr = gs->stddev * (r / (FRAND_MAX + 1.0));
+	vr = gs->stddev * (r / (FRAND32_MAX + 1.0));
 
 	return vr - gs->stddev / 2;
 }
@@ -45,7 +45,7 @@ void gauss_init(struct gauss_state *gs, unsigned long nranges, double dev,
 		unsigned int seed)
 {
 	memset(gs, 0, sizeof(*gs));
-	init_rand_seed(&gs->r, seed);
+	init_rand_seed(&gs->r, seed, 0);
 	gs->nranges = nranges;
 
 	if (dev != 0.0) {
diff --git a/lib/rand.c b/lib/rand.c
index 185b679..2e4c66e 100644
--- a/lib/rand.c
+++ b/lib/rand.c
@@ -38,12 +38,14 @@
 #include "rand.h"
 #include "../hash.h"
 
-static inline int __seed(unsigned int x, unsigned int m)
+int arch_random;
+
+static inline uint64_t __seed(uint64_t x, uint64_t m)
 {
 	return (x < m) ? x + m : x;
 }
 
-static void __init_rand(struct frand_state *state, unsigned int seed)
+static void __init_rand32(struct taus88_state *state, unsigned int seed)
 {
 	int cranks = 6;
 
@@ -54,17 +56,43 @@ static void __init_rand(struct frand_state *state, unsigned int seed)
 	state->s3 = __seed(LCG(state->s2, seed), 15);
 
 	while (cranks--)
-		__rand(state);
+		__rand32(state);
 }
 
-void init_rand(struct frand_state *state)
+static void __init_rand64(struct taus258_state *state, uint64_t seed)
 {
-	__init_rand(state, 1);
+	int cranks = 6;
+
+#define LCG64(x, seed)  ((x) * 6906969069ULL ^ (seed))
+
+	state->s1 = __seed(LCG64((2^31) + (2^17) + (2^7), seed), 1);
+	state->s2 = __seed(LCG64(state->s1, seed), 7);
+	state->s3 = __seed(LCG64(state->s2, seed), 15);
+	state->s4 = __seed(LCG64(state->s3, seed), 33);
+	state->s5 = __seed(LCG64(state->s4, seed), 49);
+
+	while (cranks--)
+		__rand64(state);
 }
 
-void init_rand_seed(struct frand_state *state, unsigned int seed)
+void init_rand(struct frand_state *state, int use64)
 {
-	__init_rand(state, seed);
+	state->use64 = use64;
+
+	if (!use64)
+		__init_rand32(&state->state32, 1);
+	else
+		__init_rand64(&state->state64, 1);
+}
+
+void init_rand_seed(struct frand_state *state, unsigned int seed, int use64)
+{
+	state->use64 = use64;
+
+	if (!use64)
+		__init_rand32(&state->state32, seed);
+	else
+		__init_rand64(&state->state64, seed);
 }
 
 void __fill_random_buf(void *buf, unsigned int len, unsigned long seed)
diff --git a/lib/rand.h b/lib/rand.h
index 089837d..cab9158 100644
--- a/lib/rand.h
+++ b/lib/rand.h
@@ -1,21 +1,69 @@
 #ifndef FIO_RAND_H
 #define FIO_RAND_H
 
-#define FRAND_MAX	(-1U)
+#include <inttypes.h>
+#include "../arch/arch.h"
 
-struct frand_state {
+#define FRAND32_MAX	(-1U)
+#define FRAND64_MAX	(-1ULL)
+
+struct taus88_state {
 	unsigned int s1, s2, s3;
 };
 
-static inline void frand_copy(struct frand_state *dst,
-			      struct frand_state *src)
+struct taus258_state {
+	uint64_t s1, s2, s3, s4, s5;
+};
+
+struct frand_state {
+	unsigned int use64;
+	union {
+		struct taus88_state state32;
+		struct taus258_state state64;
+	};
+};
+
+struct frand64_state {
+	uint64_t s1, s2, s3, s4, s5;
+};
+
+static inline uint64_t rand_max(struct frand_state *state)
+{
+	if (state->use64)
+		return FRAND64_MAX;
+	else
+		return FRAND32_MAX;
+}
+
+static inline void __frand32_copy(struct taus88_state *dst,
+				  struct taus88_state *src)
+{
+	dst->s1 = src->s1;
+	dst->s2 = src->s2;
+	dst->s3 = src->s3;
+}
+
+static inline void __frand64_copy(struct taus258_state *dst,
+				  struct taus258_state *src)
 {
 	dst->s1 = src->s1;
 	dst->s2 = src->s2;
 	dst->s3 = src->s3;
+	dst->s4 = src->s4;
+	dst->s5 = src->s5;
+}
+
+static inline void frand_copy(struct frand_state *dst, struct frand_state *src)
+{
+	if (src->use64)
+		__frand64_copy(&dst->state64, &src->state64);
+	else
+		__frand32_copy(&dst->state32, &src->state32);
+
+	dst->use64 = src->use64;
 }
 
-static inline unsigned int __rand(struct frand_state *state)
+static inline unsigned int __rand32(struct taus88_state *state)
 {
 #define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
 
@@ -26,8 +74,38 @@ static inline unsigned int __rand(struct frand_state *state)
 	return (state->s1 ^ state->s2 ^ state->s3);
 }
 
-extern void init_rand(struct frand_state *);
-extern void init_rand_seed(struct frand_state *, unsigned int seed);
+static inline uint64_t __rand64(struct taus258_state *state)
+{
+	uint64_t xval;
+
+	xval = ((state->s1 <<  1) ^ state->s1) >> 53;
+	state->s1 = ((state->s1 & 18446744073709551614ULL) << 10) ^ xval;
+
+	xval = ((state->s2 << 24) ^ state->s2) >> 50;
+	state->s2 = ((state->s2 & 18446744073709551104ULL) <<  5) ^ xval;
+
+	xval = ((state->s3 <<  3) ^ state->s3) >> 23;
+	state->s3 = ((state->s3 & 18446744073709547520ULL) << 29) ^ xval;
+
+	xval = ((state->s4 <<  5) ^ state->s4) >> 24;
+	state->s4 = ((state->s4 & 18446744073709420544ULL) << 23) ^ xval;
+
+	xval = ((state->s5 <<  3) ^ state->s5) >> 33;
+	state->s5 = ((state->s5 & 18446744073701163008ULL) <<  8) ^ xval;
+
+	return (state->s1 ^ state->s2 ^ state->s3 ^ state->s4 ^ state->s5);
+}
+
+static inline uint64_t __rand(struct frand_state *state)
+{
+	if (state->use64)
+		return __rand64(&state->state64);
+	else
+		return __rand32(&state->state32);
+}
+
+extern void init_rand(struct frand_state *, int);
+extern void init_rand_seed(struct frand_state *, unsigned int seed, int);
 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/lib/zipf.c b/lib/zipf.c
index c691bc5..d8e72b1 100644
--- a/lib/zipf.c
+++ b/lib/zipf.c
@@ -35,7 +35,7 @@ static void shared_rand_init(struct zipf_state *zs, unsigned long nranges,
 	memset(zs, 0, sizeof(*zs));
 	zs->nranges = nranges;
 
-	init_rand_seed(&zs->rand, seed);
+	init_rand_seed(&zs->rand, seed, 0);
 	zs->rand_off = __rand(&zs->rand);
 }
 
@@ -59,7 +59,7 @@ unsigned long long zipf_next(struct zipf_state *zs)
 	alpha = 1.0 / (1.0 - zs->theta);
 	eta = (1.0 - pow(2.0 / n, 1.0 - zs->theta)) / (1.0 - zs->zeta2 / zs->zetan);
 
-	rand_uni = (double) __rand(&zs->rand) / (double) FRAND_MAX;
+	rand_uni = (double) __rand(&zs->rand) / (double) FRAND32_MAX;
 	rand_z = rand_uni * zs->zetan;
 
 	if (rand_z < 1.0)
@@ -81,7 +81,7 @@ void pareto_init(struct zipf_state *zs, unsigned long nranges, double h,
 
 unsigned long long pareto_next(struct zipf_state *zs)
 {
-	double rand = (double) __rand(&zs->rand) / (double) FRAND_MAX;
+	double rand = (double) __rand(&zs->rand) / (double) FRAND32_MAX;
 	unsigned long long n = zs->nranges - 1;
 
 	return (__hash_u64(n * pow(rand, zs->pareto_pow)) + zs->rand_off) % zs->nranges;
diff --git a/options.c b/options.c
index 7f9075b..96b8b68 100644
--- a/options.c
+++ b/options.c
@@ -1897,6 +1897,11 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
 			    .oval = FIO_RAND_GEN_LFSR,
 			    .help = "Variable length LFSR",
 			  },
+			  {
+			    .ival = "tausworthe64",
+			    .oval = FIO_RAND_GEN_TAUSWORTHE64,
+			    .help = "64-bit Tausworthe variant",
+			  },
 		},
 		.category = FIO_OPT_C_IO,
 		.group	= FIO_OPT_G_RANDOM,
diff --git a/server.c b/server.c
index 519a7ee..b4137d1 100644
--- a/server.c
+++ b/server.c
@@ -1410,7 +1410,7 @@ void fio_server_send_start(struct thread_data *td)
 }
 
 int fio_server_get_verify_state(const char *name, int threadnumber,
-				void **datap)
+				void **datap, int *version)
 {
 	struct thread_io_list *s;
 	struct cmd_sendfile out;
@@ -1458,7 +1458,7 @@ fail:
 	 * the header, and the thread_io_list checksum
 	 */
 	s = rep->data + sizeof(struct verify_state_hdr);
-	if (verify_state_hdr(rep->data, s))
+	if (verify_state_hdr(rep->data, s, version))
 		goto fail;
 
 	/*
diff --git a/server.h b/server.h
index 9944719..e4da882 100644
--- a/server.h
+++ b/server.h
@@ -197,7 +197,7 @@ extern void fio_server_send_ts(struct thread_stat *, struct group_run_stats *);
 extern void fio_server_send_gs(struct group_run_stats *);
 extern void fio_server_send_du(void);
 extern void fio_server_idle_loop(void);
-extern int fio_server_get_verify_state(const char *, int, void **);
+extern int fio_server_get_verify_state(const char *, int, void **, int *);
 
 extern int fio_recv_data(int sk, void *p, unsigned int len);
 extern int fio_send_data(int sk, const void *p, unsigned int len);
diff --git a/trim.c b/trim.c
index 95c433b..4345541 100644
--- a/trim.c
+++ b/trim.c
@@ -70,13 +70,15 @@ int get_next_trim(struct thread_data *td, struct io_u *io_u)
 int io_u_should_trim(struct thread_data *td, struct io_u *io_u)
 {
 	unsigned long long val;
+	uint64_t frand_max;
 	unsigned long r;
 
 	if (!td->o.trim_percentage)
 		return 0;
 
+	frand_max = rand_max(&td->trim_state);
 	r = __rand(&td->trim_state);
-	val = (FRAND_MAX / 100ULL);
+	val = (frand_max / 100ULL);
 
 	val *= (unsigned long long) td->o.trim_percentage;
 	return r <= val;
diff --git a/verify.c b/verify.c
index aa178e9..fcdf748 100644
--- a/verify.c
+++ b/verify.c
@@ -1343,10 +1343,21 @@ struct all_io_list *get_all_io_list(int save_mask, size_t *sz)
 		s->depth = cpu_to_le64((uint64_t) td->o.iodepth);
 		s->numberio = cpu_to_le64((uint64_t) td->io_issues[DDIR_WRITE]);
 		s->index = cpu_to_le64((uint64_t) i);
-		s->rand.s[0] = cpu_to_le32(td->random_state.s1);
-		s->rand.s[1] = cpu_to_le32(td->random_state.s2);
-		s->rand.s[2] = cpu_to_le32(td->random_state.s3);
-		s->rand.s[3] = 0;
+		if (td->random_state.use64) {
+			s->rand.state64.s[0] = cpu_to_le64(td->random_state.state64.s1);
+			s->rand.state64.s[1] = cpu_to_le64(td->random_state.state64.s2);
+			s->rand.state64.s[2] = cpu_to_le64(td->random_state.state64.s3);
+			s->rand.state64.s[3] = cpu_to_le64(td->random_state.state64.s4);
+			s->rand.state64.s[4] = cpu_to_le64(td->random_state.state64.s5);
+			s->rand.state64.s[5] = 0;
+			s->rand.use64 = cpu_to_le64((uint64_t)1);
+		} else {
+			s->rand.state32.s[0] = cpu_to_le32(td->random_state.state32.s1);
+			s->rand.state32.s[1] = cpu_to_le32(td->random_state.state32.s2);
+			s->rand.state32.s[2] = cpu_to_le32(td->random_state.state32.s3);
+			s->rand.state32.s[3] = 0;
+			s->rand.use64 = 0;
+		}
 		s->name[sizeof(s->name) - 1] = '\0';
 		strncpy((char *) s->name, td->o.name, sizeof(s->name) - 1);
 		next = io_list_next(s);
@@ -1442,23 +1453,72 @@ void verify_free_state(struct thread_data *td)
 		free(td->vstate);
 }
 
-void verify_convert_assign_state(struct thread_data *td,
-				 struct thread_io_list *s)
+static struct thread_io_list *convert_v1_list(struct thread_io_list_v1 *s)
 {
+	struct thread_io_list *til;
 	int i;
 
-	s->no_comps = le64_to_cpu(s->no_comps);
-	s->depth = le64_to_cpu(s->depth);
-	s->numberio = le64_to_cpu(s->numberio);
+	til = malloc(__thread_io_list_sz(s->no_comps));
+	til->no_comps = s->no_comps;
+	til->depth = s->depth;
+	til->numberio = s->numberio;
+	til->index = s->index;
+	memcpy(til->name, s->name, sizeof(til->name));
+
+	til->rand.use64 = 0;
 	for (i = 0; i < 4; i++)
-		s->rand.s[i] = le32_to_cpu(s->rand.s[i]);
+		til->rand.state32.s[i] = s->rand.s[i];
+
 	for (i = 0; i < s->no_comps; i++)
-		s->offsets[i] = le64_to_cpu(s->offsets[i]);
+		til->offsets[i] = s->offsets[i];
+
+	return til;
+}
+
+void verify_convert_assign_state(struct thread_data *td, void *p, int version)
+{
+	struct thread_io_list *til;
+	int i;
+
+	if (version == 1) {
+		struct thread_io_list_v1 *s = p;
+
+		s->no_comps = le64_to_cpu(s->no_comps);
+		s->depth = le64_to_cpu(s->depth);
+		s->numberio = le64_to_cpu(s->numberio);
+		for (i = 0; i < 4; i++)
+			s->rand.s[i] = le32_to_cpu(s->rand.s[i]);
+		for (i = 0; i < s->no_comps; i++)
+			s->offsets[i] = le64_to_cpu(s->offsets[i]);
+
+		til = convert_v1_list(s);
+		free(s);
+	} else {
+		struct thread_io_list *s = p;
+
+		s->no_comps = le64_to_cpu(s->no_comps);
+		s->depth = le64_to_cpu(s->depth);
+		s->numberio = le64_to_cpu(s->numberio);
+		s->rand.use64 = le64_to_cpu(s->rand.use64);
+
+		if (s->rand.use64) {
+			for (i = 0; i < 6; i++)
+				s->rand.state64.s[i] = le64_to_cpu(s->rand.state64.s[i]);
+		} else {
+			for (i = 0; i < 4; i++)
+				s->rand.state32.s[i] = le32_to_cpu(s->rand.state32.s[i]);
+		}
+		for (i = 0; i < s->no_comps; i++)
+			s->offsets[i] = le64_to_cpu(s->offsets[i]);
+
+		til = p;
+	}
 
-	td->vstate = s;
+	td->vstate = til;
 }
 
-int verify_state_hdr(struct verify_state_hdr *hdr, struct thread_io_list *s)
+int verify_state_hdr(struct verify_state_hdr *hdr, struct thread_io_list *s,
+		     int *version)
 {
 	uint64_t crc;
 
@@ -1466,20 +1526,22 @@ int verify_state_hdr(struct verify_state_hdr *hdr, struct thread_io_list *s)
 	hdr->size = le64_to_cpu(hdr->size);
 	hdr->crc = le64_to_cpu(hdr->crc);
 
-	if (hdr->version != VSTATE_HDR_VERSION)
+	if (hdr->version != VSTATE_HDR_VERSION ||
+	    hdr->version != VSTATE_HDR_VERSION_V1)
 		return 1;
 
 	crc = fio_crc32c((void *)s, hdr->size);
 	if (crc != hdr->crc)
 		return 1;
 
+	*version = hdr->version;
 	return 0;
 }
 
 int verify_load_state(struct thread_data *td, const char *prefix)
 {
-	struct thread_io_list *s = NULL;
 	struct verify_state_hdr hdr;
+	void *s = NULL;
 	uint64_t crc;
 	ssize_t ret;
 	int fd;
@@ -1503,7 +1565,8 @@ int verify_load_state(struct thread_data *td, const char *prefix)
 	hdr.size = le64_to_cpu(hdr.size);
 	hdr.crc = le64_to_cpu(hdr.crc);
 
-	if (hdr.version != VSTATE_HDR_VERSION) {
+	if (hdr.version != VSTATE_HDR_VERSION &&
+	    hdr.version != VSTATE_HDR_VERSION_V1) {
 		log_err("fio: bad version in verify state header\n");
 		goto err;
 	}
@@ -1517,7 +1580,7 @@ int verify_load_state(struct thread_data *td, const char *prefix)
 		goto err;
 	}
 
-	crc = fio_crc32c((void *)s, hdr.size);
+	crc = fio_crc32c(s, hdr.size);
 	if (crc != hdr.crc) {
 		log_err("fio: verify state is corrupt\n");
 		goto err;
@@ -1525,7 +1588,7 @@ int verify_load_state(struct thread_data *td, const char *prefix)
 
 	close(fd);
 
-	verify_convert_assign_state(td, s);
+	verify_convert_assign_state(td, s, hdr.version);
 	return 0;
 err:
 	if (s)
diff --git a/verify.h b/verify.h
index 43de887..d4d6012 100644
--- a/verify.h
+++ b/verify.h
@@ -88,10 +88,22 @@ extern void fio_verify_init(struct thread_data *td);
 extern int verify_async_init(struct thread_data *);
 extern void verify_async_exit(struct thread_data *);
 
-struct thread_rand_state {
+struct thread_rand32_state {
 	uint32_t s[4];
 };
 
+struct thread_rand64_state {
+	uint64_t s[6];
+};
+
+struct thread_rand_state {
+	uint64_t use64;
+	union {
+		struct thread_rand32_state state32;
+		struct thread_rand64_state state64;
+	};
+};
+
 /*
  * For dumping current write state
  */
@@ -105,12 +117,23 @@ struct thread_io_list {
 	uint64_t offsets[0];
 };
 
+struct thread_io_list_v1 {
+	uint64_t no_comps;
+	uint64_t depth;
+	uint64_t numberio;
+	uint64_t index;
+	struct thread_rand32_state rand;
+	uint8_t name[64];
+	uint64_t offsets[0];
+};
+
 struct all_io_list {
 	uint64_t threads;
 	struct thread_io_list state[0];
 };
 
-#define VSTATE_HDR_VERSION	0x01
+#define VSTATE_HDR_VERSION_V1	0x01
+#define VSTATE_HDR_VERSION	0x02
 
 struct verify_state_hdr {
 	uint64_t version;
@@ -125,12 +148,18 @@ extern void verify_save_state(void);
 extern int verify_load_state(struct thread_data *, const char *);
 extern void verify_free_state(struct thread_data *);
 extern int verify_state_should_stop(struct thread_data *, struct io_u *);
-extern void verify_convert_assign_state(struct thread_data *, struct thread_io_list *);
-extern int verify_state_hdr(struct verify_state_hdr *, struct thread_io_list *);
+extern void verify_convert_assign_state(struct thread_data *, void *, int);
+extern int verify_state_hdr(struct verify_state_hdr *, struct thread_io_list *,
+				int *);
+
+static inline size_t __thread_io_list_sz(uint64_t depth)
+{
+	return sizeof(struct thread_io_list) + depth * sizeof(uint64_t);
+}
 
 static inline size_t thread_io_list_sz(struct thread_io_list *s)
 {
-	return sizeof(*s) + le64_to_cpu(s->depth) * sizeof(uint64_t);
+	return __thread_io_list_sz(le64_to_cpu(s->depth));
 }
 
 static inline struct thread_io_list *io_list_next(struct thread_io_list *s)
--
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