diff --git a/Makefile.in b/Makefile.in
index 31ba2f7..97b86c4 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -129,6 +129,7 @@ DEVTOOLS_SOURCE=\
thin-provisioning/thin_ll_restore.cc \
thin-provisioning/thin_show_duplicates.cc \
thin-provisioning/thin_generate_metadata.cc \
+ thin-provisioning/thin_generate_mappings.cc \
thin-provisioning/variable_chunk_stream.cc \
thin-provisioning/thin_show_metadata.cc \
thin-provisioning/thin_scan.cc \
diff --git a/thin-provisioning/commands.cc b/thin-provisioning/commands.cc
index 13dc76c..23f4b0e 100644
--- a/thin-provisioning/commands.cc
+++ b/thin-provisioning/commands.cc
@@ -23,6 +23,7 @@ thin_provisioning::register_thin_commands(base::application &app)
app.add_cmd(command::ptr(new thin_ll_restore_cmd()));
app.add_cmd(command::ptr(new thin_scan_cmd()));
app.add_cmd(command::ptr(new thin_generate_metadata_cmd()));
+ app.add_cmd(command::ptr(new thin_generate_mappings_cmd()));
app.add_cmd(command::ptr(new thin_show_duplicates_cmd()));
app.add_cmd(command::ptr(new thin_show_metadata_cmd()));
app.add_cmd(command::ptr(new thin_journal_cmd()));
diff --git a/thin-provisioning/commands.h b/thin-provisioning/commands.h
index 6b80bdb..e3a41e7 100644
--- a/thin-provisioning/commands.h
+++ b/thin-provisioning/commands.h
@@ -110,6 +110,13 @@ namespace thin_provisioning {
virtual int run(int argc, char **argv);
};
+ class thin_generate_mappings_cmd : public base::command {
+ public:
+ thin_generate_mappings_cmd();
+ virtual void usage(std::ostream &out) const;
+ virtual int run(int argc, char **argv);
+ };
+
class thin_show_metadata_cmd : public base::command {
public:
thin_show_metadata_cmd();
diff --git a/thin-provisioning/thin_generate_mappings.cc b/thin-provisioning/thin_generate_mappings.cc
new file mode 100644
index 0000000..a366eba
--- /dev/null
+++ b/thin-provisioning/thin_generate_mappings.cc
@@ -0,0 +1,207 @@
+// This file is part of the thin-provisioning-tools source.
+//
+// thin-provisioning-tools is free software: you can redistribute it
+// and/or modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// thin-provisioning-tools is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with thin-provisioning-tools. If not, see
+// .
+
+#include "base/io_generator.h"
+#include "base/output_file_requirements.h"
+#include "persistent-data/file_utils.h"
+#include "thin-provisioning/commands.h"
+#include "thin-provisioning/thin_pool.h"
+#include "version.h"
+
+#include
+#include
+#include
+
+using namespace boost;
+using namespace thin_provisioning;
+
+//----------------------------------------------------------------
+
+namespace {
+ struct flags {
+ flags()
+ : pattern("write"),
+ offset(0)
+ {
+ }
+
+ bool check_conformance();
+
+ boost::optional output;
+ base::io_pattern pattern;
+ boost::optional dev_id;
+ boost::optional block_size;
+ base::sector_t offset;
+ boost::optional size;
+ boost::optional io_size;
+ };
+
+ bool flags::check_conformance() {
+ if (!output) {
+ cerr << "No output file provided." << endl;
+ return false;
+ }
+
+ if (!dev_id) {
+ cerr << "No device id provided." << endl;
+ return false;
+ }
+
+ if (!size) {
+ cerr << "No device size specified" << endl;
+ return false;
+ }
+
+ check_output_file_requirements(*output);
+
+ return true;
+ }
+
+ //--------------------------------
+
+ thin_pool::ptr open_pool(flags const &fs) {
+ block_manager::ptr bm = open_bm(*fs.output, block_manager::READ_WRITE);
+ return thin_pool::ptr(new thin_pool(bm));
+ }
+
+ int generate_mappings(flags const &fs) {
+ thin_pool::ptr pool = open_pool(fs);
+
+ thin::ptr td = pool->open_thin(*fs.dev_id);
+
+ io_generator_options opts;
+ opts.pattern_ = fs.pattern;
+ opts.block_size_ = !fs.block_size ?
+ pool->get_data_block_size() :
+ *fs.block_size;
+ opts.offset_ = fs.offset;
+ opts.size_ = *fs.size;
+ opts.io_size_ = !fs.io_size ? *fs.size : *fs.io_size;
+ io_generator::ptr gen = create_io_generator(opts);
+
+ base::io io;
+ while (gen->has_next()) {
+ // TODO: support io.size_
+ gen->next(io);
+
+ switch (io.op_) {
+ case base::REQ_OP_READ:
+ process_read(td, pool, io.sector_);
+ break;
+ case base::REQ_OP_WRITE:
+ process_write(td, pool, io.sector_);
+ break;
+ case base::REQ_OP_DISCARD:
+ process_discard(td, pool, io.sector_);
+ break;
+ }
+ }
+
+ pool->commit();
+
+ return 0;
+ }
+}
+
+//----------------------------------------------------------------
+
+thin_generate_mappings_cmd::thin_generate_mappings_cmd()
+ : command("thin_generate_mappings")
+{
+}
+
+void
+thin_generate_mappings_cmd::usage(std::ostream &out) const
+{
+ out << "Usage: " << get_name() << " [options]\n"
+ << "Options:\n"
+ << " {-h|--help}\n"
+ << " {-o|--output}