diff --git a/bin/thin_generate_metadata b/bin/thin_generate_metadata
new file mode 120000
index 0000000..84c01e7
--- /dev/null
+++ b/bin/thin_generate_metadata
@@ -0,0 +1 @@
+pdata_tools
\ No newline at end of file
diff --git a/thin-provisioning/thin_generate_metadata.cc b/thin-provisioning/thin_generate_metadata.cc
index 4d5903d..6eb3c62 100644
--- a/thin-provisioning/thin_generate_metadata.cc
+++ b/thin-provisioning/thin_generate_metadata.cc
@@ -1,9 +1,129 @@
-#include "thin-provisioning/commands.h"
+// Copyright (C) 2016 Red Hat, Inc. All rights reserved.
+//
+// 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/output_file_requirements.h"
+#include "persistent-data/file_utils.h"
+#include "thin-provisioning/commands.h"
+#include "thin-provisioning/emitter.h"
+#include "thin-provisioning/human_readable_format.h"
+#include "thin-provisioning/metadata.h"
+#include "thin-provisioning/restore_emitter.h"
+#include "thin-provisioning/xml_format.h"
+#include "version.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace boost;
+using namespace persistent_data;
+using namespace std;
using namespace thin_provisioning;
//----------------------------------------------------------------
+namespace {
+ struct flags {
+ flags()
+ : data_block_size(128),
+ nr_data_blocks(10240),
+ nr_thins(1),
+ blocks_per_thin(1024),
+ run_lengths(1024) {
+ }
+
+ block_address data_block_size;
+ block_address nr_data_blocks;
+ unsigned nr_thins;
+ block_address blocks_per_thin;
+ block_address run_lengths;
+ optional output;
+ };
+
+ // This is how we stir in some entropy. It mixes up the data
+ // device.
+ class shuffler {
+ public:
+ shuffler(block_address nr_blocks, unsigned run_lengths)
+ : nr_blocks_(nr_blocks / run_lengths),
+ run_lengths_(run_lengths) {
+ }
+
+ block_address map(block_address b) const {
+ return reverse(b / run_lengths_) + (b % run_lengths_);
+ }
+
+ private:
+ block_address reverse(block_address b) const {
+ return nr_blocks_ - b - 1ull;
+ }
+
+ block_address nr_blocks_;
+ block_address run_lengths_;
+ };
+
+ void generate_device(emitter::ptr e, shuffler const &s, uint32_t dev_id,
+ block_address nr_blocks, block_address base) {
+
+ e->begin_device(dev_id, nr_blocks, 0, 0, 0);
+ for (unsigned b = 0; b < nr_blocks; b++)
+ e->single_map(b, s.map(base + b), 0);
+ e->end_device();
+ }
+
+ void generate_metadata(flags const &fs, emitter::ptr e) {
+ e->begin_superblock("fake metadata", 0, 0, optional(), optional(),
+ fs.data_block_size, fs.nr_data_blocks, optional());
+
+ shuffler s(fs.nr_data_blocks, fs.run_lengths);
+ for (unsigned i = 0; i < fs.nr_thins; i++)
+ generate_device(e, s, i, fs.blocks_per_thin, i * fs.blocks_per_thin);
+
+ e->end_superblock();
+ }
+
+ int create_metadata(flags const &fs) {
+ try {
+ // The block size gets updated by the restorer.
+ block_manager<>::ptr bm(open_bm(*fs.output, block_manager<>::READ_WRITE));
+ metadata::ptr md(new metadata(bm, metadata::CREATE, 128, 0));
+ emitter::ptr restorer = create_restore_emitter(md);
+
+ generate_metadata(fs, restorer);
+
+ } catch (std::exception &e) {
+ cerr << e.what() << endl;
+ return 1;
+ }
+
+ return 0;
+ }
+}
+
+//----------------------------------------------------------------
+
thin_generate_metadata_cmd::thin_generate_metadata_cmd()
: command("thin_generate_metadata")
{
@@ -12,14 +132,84 @@ thin_generate_metadata_cmd::thin_generate_metadata_cmd()
void
thin_generate_metadata_cmd::usage(std::ostream &out) const
{
-
+ out << "Usage: " << get_name() << " [options]\n"
+ << "Options:\n"
+ << " {-h|--help}\n"
+ << " --data-block-size \n"
+ << " --nr-data-blocks \n"
+ << " --nr-thins \n"
+ << " --blocks-per-thin \n"
+ << " --run-lengths \n"
+ << " {-o|--output}