Recent changes (master)
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:
HOWTO +2 -0
@@ -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
arch/arch-x86-common.h +19 -14
@@ -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
arch/arch-x86_64.h +30 -0
@@ -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; + + asmvolatile ("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; + + asmvolatile (RDSEED_LONG "\n\t" +"setc %0" + :"=qm" (ok),"=a" (*seed)); + +return 0 ; +} +#endif
backend.c +3 -2
@@ -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" );
crc/test.c +1 -1
@@ -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++) {
filesetup.c +13 -1
@@ -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;
fio.1 +3 -0
@@ -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
fio.h +1 -0
@@ -686,6 +686,7 @@ enum {enum {FIO_RAND_GEN_TAUSWORTHE =0 ,FIO_RAND_GEN_LFSR , +FIO_RAND_GEN_TAUSWORTHE64 , };enum {
init.c +25 -16
81 lines not on this page · raw message
io_u.c +21 -10
@@ -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;
lib/gauss.c +2 -2
@@ -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 ) {
lib/rand.c +35 -7
64 lines not on this page · raw message
lib/rand.h +85 -7
114 lines not on this page · raw message
lib/zipf.c +3 -3
@@ -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;
options.c +5 -0
@@ -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,
server.c +2 -2
@@ -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;/*
server.h +1 -1
@@ -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);
trim.c +3 -1
@@ -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;
verify.c +81 -18
155 lines not on this page · raw message
verify.h +34 -5
@@ -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 0x02struct 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)