[thin_generate_damage] Introduce tools to generate metadata damage
This commit is contained in:
parent
e46fabde1a
commit
d1fed5f5ec
@ -123,11 +123,13 @@ SOURCE=\
|
|||||||
thin-provisioning/xml_format.cc
|
thin-provisioning/xml_format.cc
|
||||||
|
|
||||||
DEVTOOLS_SOURCE=\
|
DEVTOOLS_SOURCE=\
|
||||||
|
thin-provisioning/damage_generator.cc \
|
||||||
thin-provisioning/thin_journal.cc \
|
thin-provisioning/thin_journal.cc \
|
||||||
thin-provisioning/thin_journal_check.cc \
|
thin-provisioning/thin_journal_check.cc \
|
||||||
thin-provisioning/thin_ll_dump.cc \
|
thin-provisioning/thin_ll_dump.cc \
|
||||||
thin-provisioning/thin_ll_restore.cc \
|
thin-provisioning/thin_ll_restore.cc \
|
||||||
thin-provisioning/thin_show_duplicates.cc \
|
thin-provisioning/thin_show_duplicates.cc \
|
||||||
|
thin-provisioning/thin_generate_damage.cc \
|
||||||
thin-provisioning/thin_generate_metadata.cc \
|
thin-provisioning/thin_generate_metadata.cc \
|
||||||
thin-provisioning/thin_generate_mappings.cc \
|
thin-provisioning/thin_generate_mappings.cc \
|
||||||
thin-provisioning/variable_chunk_stream.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_dump_cmd()));
|
||||||
app.add_cmd(command::ptr(new thin_ll_restore_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_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_metadata_cmd()));
|
||||||
app.add_cmd(command::ptr(new thin_generate_mappings_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_duplicates_cmd()));
|
||||||
|
@ -103,6 +103,13 @@ namespace thin_provisioning {
|
|||||||
virtual int run(int argc, char **argv);
|
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 {
|
class thin_generate_metadata_cmd : public base::command {
|
||||||
public:
|
public:
|
||||||
thin_generate_metadata_cmd();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
Loading…
Reference in New Issue
Block a user