From 4c07ad86c6cc6e158c70a5c625f60144db03f20d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 28 Mar 2011 09:51:09 +0200 Subject: [PATCH] Switch all random generators to be decided by use_os_rand This includes file sizing, next file, block size selection, trim state, and verify state. Signed-off-by: Jens Axboe --- filesetup.c | 13 ++++++++++--- fio.h | 32 +++++++++++++++++++++++++------- init.c | 30 +++++++++++++++++++++++++++++- io_u.c | 41 ++++++++++++++++++++++++++++++++--------- trim.c | 11 ++++++++--- 5 files changed, 104 insertions(+), 23 deletions(-) diff --git a/filesetup.c b/filesetup.c index 0454cc40..2b690c89 100644 --- a/filesetup.c +++ b/filesetup.c @@ -210,9 +210,16 @@ static unsigned long long get_rand_file_size(struct thread_data *td) unsigned long long ret, sized; long r; - r = os_random_long(&td->file_size_state); - sized = td->o.file_size_high - td->o.file_size_low; - ret = (unsigned long long) ((double) sized * (r / (OS_RAND_MAX + 1.0))); + if (td->o.use_os_rand) { + r = os_random_long(&td->file_size_state); + sized = td->o.file_size_high - td->o.file_size_low; + ret = (unsigned long long) ((double) sized * (r / (OS_RAND_MAX + 1.0))); + } else { + 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 += td->o.file_size_low; ret -= (ret % td->o.rw_min_bs); return ret; diff --git a/fio.h b/fio.h index e5607bc7..c0087e81 100644 --- a/fio.h +++ b/fio.h @@ -336,6 +336,7 @@ struct thread_data { union { unsigned int next_file; os_random_state_t next_file_state; + struct frand_state __next_file_state; }; int error; int done; @@ -359,9 +360,18 @@ struct thread_data { unsigned long rand_seeds[7]; - os_random_state_t bsrange_state; - os_random_state_t verify_state; - os_random_state_t trim_state; + union { + os_random_state_t bsrange_state; + struct frand_state __bsrange_state; + }; + union { + os_random_state_t verify_state; + struct frand_state __verify_state; + }; + union { + os_random_state_t trim_state; + struct frand_state __trim_state; + }; unsigned int verify_batch; unsigned int trim_batch; @@ -417,8 +427,10 @@ struct thread_data { /* * State for random io, a bitmap of blocks done vs not done */ - os_random_state_t random_state; - struct frand_state __random_state; + union { + os_random_state_t random_state; + struct frand_state __random_state; + }; struct timeval start; /* start of this loop */ struct timeval epoch; /* time job was started */ @@ -431,7 +443,10 @@ struct thread_data { /* * read/write mixed workload state */ - os_random_state_t rwmix_state; + union { + os_random_state_t rwmix_state; + struct frand_state __rwmix_state; + }; unsigned long rwmix_issues; enum fio_ddir rwmix_ddir; unsigned int ddir_seq_nr; @@ -467,7 +482,10 @@ struct thread_data { /* * For generating file sizes */ - os_random_state_t file_size_state; + union { + os_random_state_t file_size_state; + struct frand_state __file_size_state; + }; /* * Error counts diff --git a/init.c b/init.c index 2ae93a02..b96350a6 100644 --- a/init.c +++ b/init.c @@ -463,7 +463,7 @@ static int exists_and_not_file(const char *filename) return 1; } -void td_fill_rand_seeds(struct thread_data *td) +static void td_fill_rand_seeds_os(struct thread_data *td) { os_random_seed(td->rand_seeds[0], &td->bsrange_state); os_random_seed(td->rand_seeds[1], &td->verify_state); @@ -482,9 +482,37 @@ void td_fill_rand_seeds(struct thread_data *td) td->rand_seeds[4] = FIO_RANDSEED * td->thread_number; os_random_seed(td->rand_seeds[4], &td->random_state); +} + +static void td_fill_rand_seeds_internal(struct thread_data *td) +{ + init_rand_seed(&td->__bsrange_state, td->rand_seeds[0]); + init_rand_seed(&td->__verify_state, td->rand_seeds[1]); + init_rand_seed(&td->__rwmix_state, td->rand_seeds[2]); + + if (td->o.file_service_type == FIO_FSERVICE_RANDOM) + init_rand_seed(&td->__next_file_state, td->rand_seeds[3]); + + init_rand_seed(&td->__file_size_state, td->rand_seeds[5]); + init_rand_seed(&td->__trim_state, td->rand_seeds[6]); + + if (!td_random(td)) + return; + + if (td->o.rand_repeatable) + td->rand_seeds[4] = FIO_RANDSEED * td->thread_number; + init_rand_seed(&td->__random_state, td->rand_seeds[4]); } +void td_fill_rand_seeds(struct thread_data *td) +{ + if (td->o.use_os_rand) + td_fill_rand_seeds_os(td); + else + td_fill_rand_seeds_internal(td); +} + /* * Initialize the various random states we need (random io, block size ranges, * read/write mix, etc). diff --git a/io_u.c b/io_u.c index c6729934..787f382e 100644 --- a/io_u.c +++ b/io_u.c @@ -346,20 +346,29 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u) const int ddir = io_u->ddir; unsigned int uninitialized_var(buflen); unsigned int minbs, maxbs; - long r; + long r, rand_max; assert(ddir_rw(ddir)); minbs = td->o.min_bs[ddir]; maxbs = td->o.max_bs[ddir]; + if (td->o.use_os_rand) + rand_max = OS_RAND_MAX; + else + rand_max = FRAND_MAX; + if (minbs == maxbs) buflen = minbs; else { - r = os_random_long(&td->bsrange_state); + if (td->o.use_os_rand) + r = os_random_long(&td->bsrange_state); + else + r = __rand(&td->__bsrange_state); + if (!td->o.bssplit_nr[ddir]) { buflen = 1 + (unsigned int) ((double) maxbs * - (r / (OS_RAND_MAX + 1.0))); + (r / (rand_max + 1.0))); if (buflen < minbs) buflen = minbs; } else { @@ -371,7 +380,7 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u) buflen = bsp->bs; perc += bsp->perc; - if (r <= ((OS_RAND_MAX / 100L) * perc)) + if (r <= ((rand_max / 100L) * perc)) break; } } @@ -416,8 +425,14 @@ static inline enum fio_ddir get_rand_ddir(struct thread_data *td) unsigned int v; long r; - r = os_random_long(&td->rwmix_state); - v = 1 + (int) (100.0 * (r / (OS_RAND_MAX + 1.0))); + if (td->o.use_os_rand) { + r = os_random_long(&td->rwmix_state); + v = 1 + (int) (100.0 * (r / (OS_RAND_MAX + 1.0))); + } else { + r = __rand(&td->__rwmix_state); + v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0))); + } + if (v <= td->o.rwmix[DDIR_READ]) return DDIR_READ; @@ -833,11 +848,19 @@ static struct fio_file *get_next_file_rand(struct thread_data *td, int fno; do { - long r = os_random_long(&td->next_file_state); int opened = 0; + long r; + + if (td->o.use_os_rand) { + r = os_random_long(&td->next_file_state); + fno = (unsigned int) ((double) td->o.nr_files + * (r / (OS_RAND_MAX + 1.0))); + } else { + r = __rand(&td->__next_file_state); + fno = (unsigned int) ((double) td->o.nr_files + * (r / (FRAND_MAX + 1.0))); + } - fno = (unsigned int) ((double) td->o.nr_files - * (r / (OS_RAND_MAX + 1.0))); f = td->files[fno]; if (fio_file_done(f)) continue; diff --git a/trim.c b/trim.c index 3da1e749..a9b15d68 100644 --- a/trim.c +++ b/trim.c @@ -75,10 +75,15 @@ int io_u_should_trim(struct thread_data *td, struct io_u *io_u) if (!td->o.trim_percentage) return 0; - r = os_random_long(&td->trim_state); - val = (OS_RAND_MAX / 100ULL); - val *= (unsigned long long) td->o.trim_percentage; + if (td->o.use_os_rand) { + r = os_random_long(&td->trim_state); + val = (OS_RAND_MAX / 100ULL); + } else { + r = __rand(&td->__trim_state); + val = (FRAND_MAX / 100ULL); + } + val *= (unsigned long long) td->o.trim_percentage; return r <= val; } #endif -- 2.25.1