diff --git a/base/io_generator.cc b/base/io_generator.cc index 76af215..88c2927 100644 --- a/base/io_generator.cc +++ b/base/io_generator.cc @@ -44,25 +44,45 @@ namespace { : begin_(begin), end_(begin + (size / step) * step), step_(step), - current_(begin) { + current_(begin), + rounds_(0) { if (size < step) throw std::runtime_error("size must be greater than the step"); } + forward_sequence_generator() + : begin_(0), end_(1), step_(1), + current_(0), rounds_(0) { + } + uint64_t next() { uint64_t r = current_; current_ += step_; if (current_ >= end_) { current_ = begin_; + ++rounds_; } return r; } + void reset(uint64_t begin, uint64_t size, uint64_t step = 1) { + begin_ = begin; + end_ = begin + (size / step) * step; + step_ = step; + current_ = begin; + rounds_ = 0; + } + + uint64_t get_rounds() { + return rounds_; + } + private: uint64_t begin_; uint64_t end_; uint64_t step_; uint64_t current_; + uint64_t rounds_; }; // - The maximum generated value is not greater than (begin+size) @@ -73,21 +93,25 @@ namespace { // TODO: load random seeds random_sequence_generator(uint64_t begin, uint64_t size, - uint64_t step) + uint64_t step, + unsigned seq_nr = 1) : begin_(begin), nr_steps_(size / step), step_(step), - nr_generated_(0) { + max_forward_steps_(seq_nr), + nr_generated_(0) + { + if (!max_forward_steps_ || max_forward_steps_ > nr_steps_) + throw std::runtime_error("invalid number of forward steps"); + + if (max_forward_steps_ > 1) + reset_forward_generator(); } uint64_t next() { - uint64_t step_idx; - - bool found = true; - while (found) { - step_idx = std::rand() % nr_steps_; - found = rand_map_.member(step_idx); - } + // FIXME: eliminate if-else + uint64_t step_idx = (max_forward_steps_ > 1) ? + next_forward_step() : next_random_step(); rand_map_.add(step_idx); ++nr_generated_; @@ -101,12 +125,47 @@ namespace { } private: + void reset_forward_generator() { + uint64_t begin = next_random_step(); + unsigned seq_nr = (std::rand() % max_forward_steps_) + 1; + forward_gen_.reset(begin, seq_nr); + } + + uint64_t next_forward_step() { + uint64_t step_idx; + + bool found = true; + while (found) { + step_idx = forward_gen_.next(); + found = rand_map_.member(step_idx); + + if (found || forward_gen_.get_rounds()) + reset_forward_generator(); + } + + return step_idx; + } + + uint64_t next_random_step() const { + uint64_t step_idx; + + bool found = true; + while (found) { + step_idx = std::rand() % nr_steps_; + found = rand_map_.member(step_idx); + } + + return step_idx; + } + uint64_t begin_; uint64_t nr_steps_; uint64_t step_; + unsigned max_forward_steps_; base::run_set rand_map_; uint64_t nr_generated_; + forward_sequence_generator forward_gen_; }; //-------------------------------- @@ -187,7 +246,8 @@ namespace { if (opts.pattern_.is_random()) gen = new random_sequence_generator(opts.offset_, - opts.size_, opts.block_size_); + opts.size_, opts.block_size_, + opts.nr_seq_blocks_); else gen = new forward_sequence_generator(opts.offset_, opts.size_, opts.block_size_); diff --git a/base/io_generator.h b/base/io_generator.h index 16a78d9..cb6368f 100644 --- a/base/io_generator.h +++ b/base/io_generator.h @@ -36,6 +36,7 @@ namespace base { sector_t block_size_; sector_t size_; sector_t io_size_; + unsigned nr_seq_blocks_; }; class io_generator { diff --git a/thin-provisioning/thin_generate_mappings.cc b/thin-provisioning/thin_generate_mappings.cc index 27781f2..1301d70 100644 --- a/thin-provisioning/thin_generate_mappings.cc +++ b/thin-provisioning/thin_generate_mappings.cc @@ -47,6 +47,7 @@ namespace { base::sector_t offset; boost::optional size; boost::optional io_size; + boost::optional nr_seq_blocks; }; bool flags::check_conformance() { @@ -65,6 +66,14 @@ namespace { return false; } + if (nr_seq_blocks) { + if (!pattern.is_random()) { + cerr << "Cannot specify the sequence size" + " while doing non-random IO" << endl; + return false; + } + } + check_output_file_requirements(*output); return true; @@ -90,6 +99,7 @@ namespace { opts.offset_ = fs.offset; opts.size_ = *fs.size; opts.io_size_ = !fs.io_size ? *fs.size : *fs.io_size; + opts.nr_seq_blocks_ = !fs.nr_seq_blocks ? 1 : *fs.nr_seq_blocks; io_generator::ptr gen = create_io_generator(opts); base::io io; @@ -133,6 +143,7 @@ thin_generate_mappings_cmd::usage(std::ostream &out) const << " {--io-size} \n" << " {--rw write|trim|randwrite|randtrim|randtw}\n" << " {--size} \n" + << " {--seq-nr} \n" << " {-V|--version}" << endl; } @@ -150,6 +161,7 @@ thin_generate_mappings_cmd::run(int argc, char **argv) { "offset", required_argument, NULL, 3 }, { "size", required_argument, NULL, 4 }, { "io-size", required_argument, NULL, 5 }, + { "seq-nr", required_argument, NULL, 6 }, { "version", no_argument, NULL, 'V' }, { NULL, no_argument, NULL, 0 } }; @@ -184,6 +196,10 @@ thin_generate_mappings_cmd::run(int argc, char **argv) fs.io_size = parse_uint64(optarg, "io_size"); break; + case 6: + fs.nr_seq_blocks = parse_uint64(optarg, "seq_nr"); + break; + case 'V': cout << THIN_PROVISIONING_TOOLS_VERSION << endl; return 0;