X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=lib%2Frand.c;h=185b679e7c1365956cd80e40d433dc8fa41a951e;hp=7c6fed1fabbcc01f1803f00521d881a9c9662603;hb=74a92cdd178ac5434d2bbbc1649fe66ff341c1d0;hpb=3545a109a2cfe5ab22969ef453dc049db47f0b68 diff --git a/lib/rand.c b/lib/rand.c index 7c6fed1f..185b679e 100644 --- a/lib/rand.c +++ b/lib/rand.c @@ -33,6 +33,8 @@ */ +#include +#include #include "rand.h" #include "../hash.h" @@ -67,11 +69,26 @@ void init_rand_seed(struct frand_state *state, unsigned int seed) void __fill_random_buf(void *buf, unsigned int len, unsigned long seed) { - long *ptr = buf; - - while ((void *) ptr - buf < len) { - *ptr = seed; - ptr++; + void *ptr = buf; + + while (len) { + int this_len; + + if (len >= sizeof(int64_t)) { + *((int64_t *) ptr) = seed; + this_len = sizeof(int64_t); + } else if (len >= sizeof(int32_t)) { + *((int32_t *) ptr) = seed; + this_len = sizeof(int32_t); + } else if (len >= sizeof(int16_t)) { + *((int16_t *) ptr) = seed; + this_len = sizeof(int16_t); + } else { + *((int8_t *) ptr) = seed; + this_len = sizeof(int8_t); + } + ptr += this_len; + len -= this_len; seed *= GOLDEN_RATIO_PRIME; seed >>= 3; } @@ -88,3 +105,92 @@ unsigned long fill_random_buf(struct frand_state *fs, void *buf, __fill_random_buf(buf, len, r); return r; } + +void fill_pattern(void *p, unsigned int len, char *pattern, + unsigned int pattern_bytes) +{ + switch (pattern_bytes) { + case 0: + assert(0); + break; + case 1: + memset(p, pattern[0], len); + break; + default: { + unsigned int i = 0, size = 0; + unsigned char *b = p; + + while (i < len) { + size = pattern_bytes; + if (size > (len - i)) + size = len - i; + memcpy(b+i, pattern, size); + i += size; + } + break; + } + } +} + +void __fill_random_buf_percentage(unsigned long seed, void *buf, + unsigned int percentage, + unsigned int segment, unsigned int len, + char *pattern, unsigned int pbytes) +{ + unsigned int this_len; + + if (percentage == 100) { + if (pbytes) + fill_pattern(buf, len, pattern, pbytes); + else + memset(buf, 0, len); + return; + } + + if (segment > len) + segment = len; + + while (len) { + /* + * Fill random chunk + */ + this_len = (segment * (100 - percentage)) / 100; + if (this_len > len) + this_len = len; + + __fill_random_buf(buf, this_len, seed); + + len -= this_len; + if (!len) + break; + buf += this_len; + + if (this_len > len) + this_len = len; + else if (len - this_len <= sizeof(long)) + this_len = len; + + if (pbytes) + fill_pattern(buf, this_len, pattern, pbytes); + else + memset(buf, 0, this_len); + + len -= this_len; + buf += this_len; + } +} + +unsigned long fill_random_buf_percentage(struct frand_state *fs, void *buf, + unsigned int percentage, + unsigned int segment, unsigned int len, + char *pattern, unsigned int pbytes) +{ + unsigned long r = __rand(fs); + + if (sizeof(int) != sizeof(long *)) + r *= (unsigned long) __rand(fs); + + __fill_random_buf_percentage(r, buf, percentage, segment, len, + pattern, pbytes); + return r; +}