static int __get_next_rand_offset(struct thread_data *td, struct fio_file *f, enum fio_ddir ddir, uint64_t *b) { uint64_t r, lastb; lastb = last_block(td, f, ddir); if (!lastb) return 1; if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE) { uint64_t rmax; rmax = td->o.use_os_rand ? OS_RAND_MAX : FRAND_MAX; if (td->o.use_os_rand) { rmax = OS_RAND_MAX; r = os_random_long(&td->random_state); } else { rmax = FRAND_MAX; r = __rand(&td->__random_state); } dprint(FD_RANDOM, "off rand %llu\n", (unsigned long long) r); *b = (lastb - 1) * (r / ((uint64_t) rmax + 1.0)); } else { uint64_t off = 0; if (lfsr_next(&f->lfsr, &off, lastb)) return 1; *b = off; } /* * if we are not maintaining a random map, we are done. */ if (!file_randommap(td, f)) goto ret; /* * calculate map offset and check if it's free */ if (random_map_free(f, *b)) goto ret; dprint(FD_RANDOM, "get_next_rand_offset: offset %llu busy\n", (unsigned long long) *b); *b = axmap_next_free(f->io_axmap, *b); if (*b == (uint64_t) -1ULL) return 1; ret: return 0; }
static int get_next_rand_offset(struct thread_data *td, struct fio_file *f, enum fio_ddir ddir, unsigned long long *b) { unsigned long long r, lastb; int loops = 5; lastb = last_block(td, f, ddir); if (!lastb) return 1; do { r = os_random_long(&td->random_state); dprint(FD_RANDOM, "off rand %llu\n", r); *b = (lastb - 1) * (r / ((unsigned long long) OS_RAND_MAX + 1.0)); /* * if we are not maintaining a random map, we are done. */ if (!file_randommap(td, f)) return 0; /* * calculate map offset and check if it's free */ if (random_map_free(f, *b)) return 0; dprint(FD_RANDOM, "get_next_rand_offset: offset %llu busy\n", *b); } while (--loops); /* * we get here, if we didn't suceed in looking up a block. generate * a random start offset into the filemap, and find the first free * block from there. */ loops = 10; do { f->last_free_lookup = (f->num_maps - 1) * (r / (OS_RAND_MAX + 1.0)); if (!get_next_free_block(td, f, ddir, b)) return 0; r = os_random_long(&td->random_state); } while (--loops); /* * that didn't work either, try exhaustive search from the start */ f->last_free_lookup = 0; return get_next_free_block(td, f, ddir, b); }
static int __get_next_rand_offset(struct thread_data *td, struct fio_file *f, enum fio_ddir ddir, uint64_t *b) { uint64_t r; 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)); } else { uint64_t off = 0; assert(fio_file_lfsr(f)); if (lfsr_next(&f->lfsr, &off)) return 1; *b = off; } /* * if we are not maintaining a random map, we are done. */ if (!file_randommap(td, f)) goto ret; /* * calculate map offset and check if it's free */ if (random_map_free(f, *b)) goto ret; dprint(FD_RANDOM, "get_next_rand_offset: offset %llu busy\n", (unsigned long long) *b); *b = axmap_next_free(f->io_axmap, *b); if (*b == (uint64_t) -1ULL) return 1; ret: return 0; }
/* * Mark a given offset as used in the map. */ static void mark_random_map(struct thread_data *td, struct io_u *io_u) { unsigned int min_bs = td->o.rw_min_bs; struct fio_file *f = io_u->file; unsigned long long block; unsigned int blocks, nr_blocks; int busy_check; block = (io_u->offset - f->file_offset) / (unsigned long long) min_bs; nr_blocks = (io_u->buflen + min_bs - 1) / min_bs; blocks = 0; busy_check = !(io_u->flags & IO_U_F_BUSY_OK); while (nr_blocks) { unsigned int idx, bit; unsigned long mask, this_blocks; /* * If we have a mixed random workload, we may * encounter blocks we already did IO to. */ if (!busy_check) { blocks = nr_blocks; break; } if ((td->o.ddir_seq_nr == 1) && !random_map_free(f, block)) break; idx = RAND_MAP_IDX(f, block); bit = RAND_MAP_BIT(f, block); fio_assert(td, idx < f->num_maps); this_blocks = nr_blocks; if (this_blocks + bit > BLOCKS_PER_MAP) this_blocks = BLOCKS_PER_MAP - bit; do { if (this_blocks == BLOCKS_PER_MAP) mask = -1UL; else mask = ((1UL << this_blocks) - 1) << bit; if (!(f->file_map[idx] & mask)) break; this_blocks--; } while (this_blocks); if (!this_blocks) break; f->file_map[idx] |= mask; nr_blocks -= this_blocks; blocks += this_blocks; block += this_blocks; } if ((blocks * min_bs) < io_u->buflen) io_u->buflen = blocks * min_bs; }