[thin_generate_damage] Introduce tools to generate metadata damage
This commit is contained in:
		| @@ -123,11 +123,13 @@ SOURCE=\ | ||||
| 	thin-provisioning/xml_format.cc | ||||
|  | ||||
| DEVTOOLS_SOURCE=\ | ||||
| 	thin-provisioning/damage_generator.cc \ | ||||
| 	thin-provisioning/thin_journal.cc \ | ||||
| 	thin-provisioning/thin_journal_check.cc \ | ||||
| 	thin-provisioning/thin_ll_dump.cc \ | ||||
| 	thin-provisioning/thin_ll_restore.cc \ | ||||
| 	thin-provisioning/thin_show_duplicates.cc \ | ||||
| 	thin-provisioning/thin_generate_damage.cc \ | ||||
| 	thin-provisioning/thin_generate_metadata.cc \ | ||||
| 	thin-provisioning/thin_generate_mappings.cc \ | ||||
| 	thin-provisioning/variable_chunk_stream.cc \ | ||||
|   | ||||
| @@ -22,6 +22,7 @@ thin_provisioning::register_thin_commands(base::application &app) | ||||
| 	app.add_cmd(command::ptr(new thin_ll_dump_cmd())); | ||||
| 	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_damage_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())); | ||||
|   | ||||
| @@ -103,6 +103,13 @@ namespace thin_provisioning { | ||||
| 		virtual int run(int argc, char **argv); | ||||
| 	}; | ||||
|  | ||||
| 	class thin_generate_damage_cmd : public base::command { | ||||
| 	public: | ||||
| 		thin_generate_damage_cmd(); | ||||
| 		virtual void usage(std::ostream &out) const; | ||||
| 		virtual int run(int argc, char **argv); | ||||
| 	}; | ||||
|  | ||||
| 	class thin_generate_metadata_cmd : public base::command { | ||||
| 	public: | ||||
| 		thin_generate_metadata_cmd(); | ||||
|   | ||||
							
								
								
									
										66
									
								
								thin-provisioning/damage_generator.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								thin-provisioning/damage_generator.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| #include "damage_generator.h" | ||||
|  | ||||
| using namespace thin_provisioning; | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| namespace { | ||||
| 	void find_blocks(space_map::ptr sm, | ||||
| 			 block_address nr_blocks, | ||||
| 			 ref_t expected, | ||||
| 			 std::set<block_address> &found) { | ||||
| 		block_address sm_size = sm->get_nr_blocks(); | ||||
| 		base::run_set<block_address> visited; | ||||
| 		block_address nr_visited = 0; | ||||
|  | ||||
| 		srand(time(NULL)); | ||||
| 		while (nr_blocks) { | ||||
| 			if (nr_visited == sm_size) | ||||
| 				break; | ||||
|  | ||||
| 			block_address b = rand() % sm_size; | ||||
| 			if (visited.member(b)) | ||||
| 				continue; | ||||
|  | ||||
| 			ref_t c = sm->get_count(b); | ||||
| 			if (c == expected) { | ||||
| 				found.insert(b); | ||||
| 				--nr_blocks; | ||||
| 			} | ||||
|  | ||||
| 			visited.add(b); | ||||
| 			++nr_visited; | ||||
| 		} | ||||
|  | ||||
| 		if (nr_blocks) { | ||||
| 			ostringstream out; | ||||
| 			out << "cannot find " << (nr_blocks + found.size()) | ||||
| 			    << " blocks of ref-count " << expected; | ||||
| 			throw runtime_error(out.str()); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| damage_generator::damage_generator(block_manager::ptr bm) | ||||
| { | ||||
| 	md_ = metadata::ptr(new metadata(bm, true)); | ||||
| } | ||||
|  | ||||
| void damage_generator::commit() | ||||
| { | ||||
| 	md_->commit(); | ||||
| } | ||||
|  | ||||
| void damage_generator::create_metadata_leaks(block_address nr_leaks, | ||||
| 					     ref_t expected, ref_t actual) | ||||
| { | ||||
| 	std::set<block_address> leaks; | ||||
| 	find_blocks(md_->metadata_sm_, nr_leaks, expected, leaks); | ||||
|  | ||||
| 	for (auto const &b : leaks) | ||||
| 		md_->metadata_sm_->set_count(b, actual); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
							
								
								
									
										22
									
								
								thin-provisioning/damage_generator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								thin-provisioning/damage_generator.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #ifndef METADATA_DAMAGE_GENERATOR_H | ||||
| #define METADATA_DAMAGE_GENERATOR_H | ||||
|  | ||||
| #include "metadata.h" | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| class damage_generator { | ||||
| public: | ||||
| 	typedef std::shared_ptr<damage_generator> ptr; | ||||
|  | ||||
| 	damage_generator(block_manager::ptr bm); | ||||
| 	void commit(); | ||||
| 	void create_metadata_leaks(block_address nr_leaks, ref_t expected, ref_t actual); | ||||
|  | ||||
| private: | ||||
| 	thin_provisioning::metadata::ptr md_; | ||||
| }; | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										144
									
								
								thin-provisioning/thin_generate_damage.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								thin-provisioning/thin_generate_damage.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| #include "base/output_file_requirements.h" | ||||
| #include "persistent-data/file_utils.h" | ||||
| #include "thin-provisioning/commands.h" | ||||
| #include "thin-provisioning/damage_generator.h" | ||||
| #include "version.h" | ||||
|  | ||||
| #include <getopt.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| using namespace persistent_data; | ||||
| using namespace thin_provisioning; | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| namespace { | ||||
| 	struct flags { | ||||
| 		enum damage_operations { | ||||
| 			DAMAGE_OP_NONE, | ||||
| 			DAMAGE_OP_CREATE_METADATA_LEAKS, | ||||
| 			DAMAGE_OP_LAST | ||||
| 		}; | ||||
|  | ||||
| 		flags() | ||||
| 			: op(DAMAGE_OP_NONE), | ||||
| 			  nr_blocks(0), | ||||
| 			  expected_rc(0), | ||||
| 			  actual_rc(0) { | ||||
| 		} | ||||
|  | ||||
| 		bool check_conformance(); | ||||
|  | ||||
| 		damage_operations op; | ||||
| 		string output; | ||||
| 		block_address nr_blocks; | ||||
| 		ref_t expected_rc; | ||||
| 		ref_t actual_rc; | ||||
| 	}; | ||||
|  | ||||
| 	bool flags::check_conformance() { | ||||
| 		if (op == DAMAGE_OP_NONE || op >= DAMAGE_OP_LAST) { | ||||
| 			cerr << "Invalid operation." << endl; | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (!output.size()) { | ||||
| 			cerr << "No output file provided." << endl; | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (!nr_blocks) { | ||||
| 			cerr << "Invalid number of blocks" << endl; | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (op == DAMAGE_OP_CREATE_METADATA_LEAKS && | ||||
| 		    expected_rc == actual_rc) { | ||||
| 			cerr << "Invalid reference count parameters" << endl; | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		check_output_file_requirements(output); | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	int generate_damage(flags const &fs) { | ||||
| 		block_manager::ptr bm = open_bm(fs.output, block_manager::READ_WRITE); | ||||
| 		damage_generator::ptr gen = damage_generator::ptr(new damage_generator(bm)); | ||||
|  | ||||
| 		switch (fs.op) { | ||||
| 		case flags::DAMAGE_OP_CREATE_METADATA_LEAKS: | ||||
| 			gen->create_metadata_leaks(fs.nr_blocks, fs.expected_rc, fs.actual_rc); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		gen->commit(); | ||||
|  | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| thin_generate_damage_cmd::thin_generate_damage_cmd() | ||||
| 	: command("thin_generate_damage") | ||||
| { | ||||
| } | ||||
|  | ||||
| void | ||||
| thin_generate_damage_cmd::usage(std::ostream &out) const | ||||
| { | ||||
| } | ||||
|  | ||||
| int | ||||
| thin_generate_damage_cmd::run(int argc, char **argv) | ||||
| { | ||||
| 	int c; | ||||
| 	struct flags fs; | ||||
| 	const char *shortopts = "ho:V"; | ||||
| 	const struct option longopts[] = { | ||||
| 		{ "help", no_argument, NULL, 'h' }, | ||||
| 		{ "output", required_argument, NULL, 'o' }, | ||||
| 		{ "create-metadata-leaks", no_argument, NULL, 1 }, | ||||
| 		{ "nr-blocks", required_argument, NULL, 1001 }, | ||||
| 		{ "expected", required_argument, NULL, 1002 }, | ||||
| 		{ "actual", required_argument, NULL, 1003 }, | ||||
| 		{ "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); | ||||
| 			break; | ||||
| 		case 'o': | ||||
| 			fs.output = optarg; | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			fs.op = flags::DAMAGE_OP_CREATE_METADATA_LEAKS; | ||||
| 			break; | ||||
| 		case 1001: | ||||
| 			fs.nr_blocks = parse_uint64(optarg, "nr_blocks"); | ||||
| 			break; | ||||
| 		case 1002: | ||||
| 			fs.expected_rc = parse_uint64(optarg, "expected"); | ||||
| 			break; | ||||
| 		case 1003: | ||||
| 			fs.actual_rc = parse_uint64(optarg, "actual"); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!fs.check_conformance()) { | ||||
| 		usage(cerr); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	return generate_damage(fs); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
		Reference in New Issue
	
	Block a user