[thin_generate_mappings] Introduce the mapping generation tool
This commit is contained 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 \ | ||||
|   | ||||
| @@ -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())); | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
							
								
								
									
										207
									
								
								thin-provisioning/thin_generate_mappings.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								thin-provisioning/thin_generate_mappings.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| // <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| #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 <boost/optional.hpp> | ||||
| #include <getopt.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| using namespace boost; | ||||
| using namespace thin_provisioning; | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| namespace { | ||||
| 	struct flags { | ||||
| 		flags() | ||||
| 			: pattern("write"), | ||||
| 			  offset(0) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		bool check_conformance(); | ||||
|  | ||||
| 		boost::optional<string> output; | ||||
| 		base::io_pattern pattern; | ||||
| 		boost::optional<unsigned> dev_id; | ||||
| 		boost::optional<base::sector_t> block_size; | ||||
| 		base::sector_t offset; | ||||
| 		boost::optional<base::sector_t> size; | ||||
| 		boost::optional<base::sector_t> 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} <output device or file>\n" | ||||
| 	    << "  {--dev-id} <dev-id>\n" | ||||
| 	    << "  {--offset} <offset>\n" | ||||
|             << "  {--io-size} <io_size>\n" | ||||
| 	    << "  {--rw write|trim|randwrite|randtrim|randtw}\n" | ||||
|             << "  {--size} <size>\n" | ||||
| 	    << "  {-V|--version}" << endl; | ||||
| } | ||||
|  | ||||
| int | ||||
| thin_generate_mappings_cmd::run(int argc, char **argv) | ||||
| { | ||||
| 	int c; | ||||
| 	struct flags fs; | ||||
| 	const char *shortopts = "hi:o:qV"; | ||||
| 	const struct option longopts[] = { | ||||
| 		{ "help", no_argument, NULL, 'h' }, | ||||
| 		{ "output", required_argument, NULL, 'o' }, | ||||
| 		{ "dev-id", required_argument, NULL, 1 }, | ||||
| 		{ "rw", required_argument, NULL, 2 }, | ||||
| 		{ "offset", required_argument, NULL, 3 }, | ||||
| 		{ "size", required_argument, NULL, 4 }, | ||||
| 		{ "io-size", required_argument, NULL, 5 }, | ||||
| 		{ "version", no_argument, NULL, 'V' }, | ||||
| 		{ NULL, no_argument, NULL, 0 } | ||||
| 	}; | ||||
|  | ||||
| 	while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { | ||||
| 		switch(c) { | ||||
| 		case 'h': | ||||
| 			usage(cout); | ||||
| 			return 0; | ||||
|  | ||||
| 		case 'o': | ||||
| 			fs.output = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case 1: | ||||
| 			fs.dev_id = parse_uint64(optarg, "dev_id"); | ||||
| 			break; | ||||
|  | ||||
| 		case 2: | ||||
| 			fs.pattern.parse(optarg); | ||||
| 			break; | ||||
|  | ||||
| 		case 3: | ||||
| 			fs.offset = parse_uint64(optarg, "offset"); | ||||
| 			break; | ||||
|  | ||||
| 		case 4: | ||||
| 			fs.size = parse_uint64(optarg, "size"); | ||||
| 			break; | ||||
|  | ||||
| 		case 5: | ||||
| 			fs.io_size = parse_uint64(optarg, "io_size"); | ||||
| 			break; | ||||
|  | ||||
| 		case 'V': | ||||
| 			cout << THIN_PROVISIONING_TOOLS_VERSION << endl; | ||||
| 			return 0; | ||||
|  | ||||
| 		default: | ||||
| 			usage(cerr); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!fs.check_conformance()) { | ||||
| 		usage(cerr); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	return generate_mappings(fs); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
		Reference in New Issue
	
	Block a user