Merge pull request #154 from mingnus/main

thin development tools update
This commit is contained in:
Joe Thornber 2020-11-24 09:31:23 +00:00 committed by GitHub
commit 5af95167b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 324 additions and 85 deletions

41
Cargo.lock generated
View File

@ -65,6 +65,18 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bitvec"
version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "byteorder"
version = "1.3.4"
@ -188,6 +200,12 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "funty"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ba62103ce691c2fd80fbae2213dfdda9ce60804973ac6b6e97de818ea7f52c8"
[[package]]
name = "futures"
version = "0.3.5"
@ -396,8 +414,11 @@ dependencies = [
[[package]]
name = "nom"
version = "6.0.0-alpha1"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4489ccc7d668957ddf64af7cd027c081728903afa6479d35da7e99bf5728f75f"
dependencies = [
"bitvec",
"lexical-core",
"memchr",
"version_check",
@ -555,6 +576,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "rand"
version = "0.7.3"
@ -683,6 +710,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "tap"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e"
[[package]]
name = "tempfile"
version = "3.1.0"
@ -895,3 +928,9 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "wyz"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"

View File

@ -21,7 +21,7 @@ io-uring = "0.3"
indicatif = "0.15"
libc = "0.2.71"
nix = "0.17"
nom = { path = "/home/ejt/builds/nom/" }
nom = "6.0.0"
num_cpus = "1.13"
num-derive = "0.3"
num-traits = "0.2"

View File

@ -134,6 +134,7 @@ DEVTOOLS_SOURCE=\
thin-provisioning/thin_generate_metadata.cc \
thin-provisioning/thin_generate_mappings.cc \
thin-provisioning/variable_chunk_stream.cc \
thin-provisioning/thin_patch_superblock.cc \
thin-provisioning/thin_show_metadata.cc \
thin-provisioning/thin_scan.cc \
ui/ui.cc

View File

@ -25,6 +25,7 @@ thin_provisioning::register_thin_commands(base::application &app)
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_patch_superblock_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()));

View File

@ -124,6 +124,13 @@ namespace thin_provisioning {
virtual int run(int argc, char **argv);
};
class thin_patch_superblock_cmd : public base::command {
public:
thin_patch_superblock_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();

View File

@ -22,47 +22,7 @@ using namespace thin_provisioning;
//----------------------------------------------------------------
namespace local {
class application {
public:
application(string const &cmd)
: cmd_(cmd) {
}
void usage(ostream &out) {
out << "Usage: " << cmd_ << " [options] <device or file>\n"
<< "Options:\n"
<< " {--thin1, --snap1}\n"
<< " {--thin2, --snap2}\n"
<< " {-m, --metadata-snap} [block#]\n"
<< " {--verbose}\n"
<< " {-h|--help}\n"
<< " {-V|--version}" << endl;
}
void die(string const &msg) {
cerr << msg << endl;
usage(cerr);
exit(1);
}
uint64_t parse_int(string const &str, string const &desc) {
try {
return boost::lexical_cast<uint64_t>(str);
} catch (...) {
ostringstream out;
out << "Couldn't parse " << desc << ": '" << str << "'";
die(out.str());
}
return 0; // never get here
}
private:
string cmd_;
};
namespace {
struct flags {
flags()
: verbose(false),
@ -76,6 +36,8 @@ namespace local {
boost::optional<uint64_t> metadata_snap;
boost::optional<uint64_t> snap1;
boost::optional<uint64_t> snap2;
boost::optional<uint64_t> root1;
boost::optional<uint64_t> root2;
};
//--------------------------------
@ -96,13 +58,6 @@ namespace local {
uint64_t vbegin_, dbegin_, len_;
};
ostream &operator <<(ostream &out, mapping const &m) {
out << "mapping[vbegin = " << m.vbegin_
<< ", dbegin = " << m.dbegin_
<< ", len = " << m.len_ << "]";
return out;
}
//--------------------------------
template <typename Container>
@ -528,9 +483,26 @@ namespace local {
out << "</superblock>\n";
}
void begin_diff(indented_stream &out, uint64_t snap1, uint64_t snap2) {
// FIXME: always show the blocknr?
void begin_diff(indented_stream &out,
boost::optional<uint64_t> snap1,
boost::optional<uint64_t> root1,
boost::optional<uint64_t> snap2,
boost::optional<uint64_t> root2) {
out.indent();
out << "<diff left=\"" << snap1 << "\" right=\"" << snap2 << "\">\n";
out << "<diff";
if (snap1)
out << " left=\"" << *snap1 << "\"";
else if (root1)
out << " left_root=\"" << *root1 << "\"";
if (snap2)
out << " right=\"" << *snap2 << "\"";
else if (root2)
out << " right_root=\"" << *root2 << "\"";
out << ">\n";
out.inc();
}
@ -540,7 +512,7 @@ namespace local {
out << "</diff>\n";
}
void delta_(application &app, flags const &fs) {
void delta_(flags const &fs) {
mapping_recorder mr1;
mapping_recorder mr2;
damage_visitor damage_v;
@ -552,25 +524,33 @@ namespace local {
metadata::ptr md(fs.use_metadata_snap ? new metadata(bm, fs.metadata_snap) : new metadata(bm));
sb = md->sb_;
dev_tree::key k = {*fs.snap1};
boost::optional<uint64_t> snap1_root = md->mappings_top_level_->lookup(k);
boost::optional<uint64_t> snap1_root;
if (fs.snap1) {
dev_tree::key k = {*fs.snap1};
snap1_root = md->mappings_top_level_->lookup(k);
} else if (fs.root1)
snap1_root = *fs.root1;
if (!snap1_root) {
ostringstream out;
out << "Unable to find mapping tree for snap1 (" << *fs.snap1 << ")";
app.die(out.str());
throw std::runtime_error(out.str());
}
single_mapping_tree snap1(*md->tm_, *snap1_root,
mapping_tree_detail::block_traits::ref_counter(md->tm_->get_sm()));
k[0] = *fs.snap2;
boost::optional<uint64_t> snap2_root = md->mappings_top_level_->lookup(k);
boost::optional<uint64_t> snap2_root;
if (fs.snap2) {
dev_tree::key k = {*fs.snap2};
snap2_root = md->mappings_top_level_->lookup(k);
} else if (fs.root2)
snap2_root = *fs.root2;
if (!snap2_root) {
ostringstream out;
out << "Unable to find mapping tree for snap2 (" << *fs.snap2 << ")";
app.die(out.str());
throw std::runtime_error(out.str());
}
single_mapping_tree snap2(*md->tm_, *snap2_root,
@ -593,7 +573,7 @@ namespace local {
sb.metadata_snap_ ?
boost::optional<block_address>(sb.metadata_snap_) :
boost::optional<block_address>());
begin_diff(is, *fs.snap1, *fs.snap2);
begin_diff(is, fs.snap1, fs.root1, fs.snap2, fs.root2);
if (fs.verbose) {
verbose_emitter e(is);
@ -607,12 +587,12 @@ namespace local {
end_superblock(is);
}
int delta(application &app, flags const &fs) {
int delta(flags const &fs) {
try {
delta_(app, fs);
delta_(fs);
} catch (exception const &e) {
app.die(e.what());
return 1; // never get here
cerr << e.what() << endl;
return 1;
}
return 0;
@ -631,77 +611,95 @@ thin_delta_cmd::thin_delta_cmd()
void
thin_delta_cmd::usage(std::ostream &out) const
{
// FIXME: finish
out << "Usage: " << get_name() << " [options] <device or file>\n"
<< "Options:\n"
<< " {--thin1, --snap1, --root1}\n"
<< " {--thin2, --snap2, --root2}\n"
<< " {-m, --metadata-snap} [block#]\n"
<< " {--verbose}\n"
<< " {-h|--help}\n"
<< " {-V|--version}" << endl;
}
int
thin_delta_cmd::run(int argc, char **argv)
{
using namespace local;
int c;
flags fs;
local::application app(basename(argv[0]));
char const shortopts[] = "hVm::";
option const longopts[] = {
{ "help", no_argument, NULL, 'h' },
{ "metadata-snap", optional_argument, NULL, 'm' },
{ "version", no_argument, NULL, 'V' },
{ "thin1", required_argument, NULL, 1 },
{ "snap1", required_argument, NULL, 1 },
{ "thin2", required_argument, NULL, 2 },
{ "snap2", required_argument, NULL, 2 },
{ "metadata-snap", optional_argument, NULL, 'm' },
{ "verbose", no_argument, NULL, 4 },
{ "root1", required_argument, NULL, 5 },
{ "root2", required_argument, NULL, 6 },
{ NULL, no_argument, NULL, 0 }
};
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (c) {
case 'h':
app.usage(cout);
usage(cout);
return 0;
case 'm':
fs.use_metadata_snap = true;
if (optarg)
fs.metadata_snap = parse_uint64(optarg, "metadata snapshot block");
break;
case 'V':
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
return 0;
case 1:
fs.snap1 = app.parse_int(optarg, "thin id 1");
fs.snap1 = parse_uint64(optarg, "thin id 1");
break;
case 2:
fs.snap2 = app.parse_int(optarg, "thin id 2");
break;
case 'm':
fs.use_metadata_snap = true;
if (optarg)
fs.metadata_snap = app.parse_int(optarg, "metadata snapshot block");
fs.snap2 = parse_uint64(optarg, "thin id 2");
break;
case 4:
fs.verbose = true;
break;
case 5:
fs.root1 = parse_uint64(optarg, "thin root 1");
break;
case 6:
fs.root2 = parse_uint64(optarg, "thin root 2");
break;
default:
app.usage(cerr);
usage(cerr);
return 1;
}
}
if (argc == optind)
app.die("No input device provided.");
die("No input device provided.");
else
fs.dev = argv[optind];
if (!fs.snap1)
app.die("--snap1 not specified.");
if (!fs.snap1 && !fs.root1)
die("--snap1 or --root1 not specified.");
if (!!fs.snap1 && !!fs.root1)
die("--snap1 and --root1 are not compatible.");
if (!fs.snap2)
app.die("--snap2 not specified.");
if (!fs.snap2 && !fs.root2)
die("--snap2 or --root2 not specified.");
if (!!fs.snap2 && !!fs.root2)
die("--snap2 and --root2 are not compatible.");
return delta(app, fs);
return delta(fs);
}
//----------------------------------------------------------------

View File

@ -0,0 +1,193 @@
#include <getopt.h>
#include "persistent-data/file_utils.h"
#include "persistent-data/space-maps/disk_structures.h"
#include "thin-provisioning/commands.h"
#include "thin-provisioning/metadata.h"
#include "thin-provisioning/superblock.h"
#include "version.h"
using namespace persistent_data;
using namespace sm_disk_detail;
using namespace thin_provisioning;
//----------------------------------------------------------------
namespace {
struct flags {
flags();
bool check_conformance();
string output;
boost::optional<uint64_t> transaction_id;
block_address data_mapping_root;
block_address device_details_root;
block_address metadata_bitmap_root;
block_address metadata_ref_count_root;
block_address data_bitmap_root;
block_address data_ref_count_root;
};
flags::flags()
: data_mapping_root(0), device_details_root(0),
metadata_bitmap_root(0), metadata_ref_count_root(0),
data_bitmap_root(0), data_ref_count_root(0) {
}
bool flags::check_conformance() {
if (!output.size())
return false;
return true;
}
void patch_space_map_root(void *root,
block_address bitmap_root,
block_address ref_count_root) {
sm_disk_detail::sm_root v;
sm_disk_detail::sm_root_disk d;
memcpy(&d, root, sizeof(d));
sm_root_traits::unpack(d, v);
if (bitmap_root)
v.bitmap_root_ = bitmap_root;
if (ref_count_root)
v.ref_count_root_ = ref_count_root;
sm_root_traits::pack(v, d);
memcpy(root, &d, sizeof(d));
}
int patch_superblock(flags const &fs) {
block_manager::ptr bm = open_bm(fs.output, block_manager::READ_WRITE);
superblock_detail::superblock sb = read_superblock(bm, superblock_detail::SUPERBLOCK_LOCATION);
if (fs.transaction_id)
sb.trans_id_ = *fs.transaction_id;
if (fs.data_mapping_root)
sb.data_mapping_root_ = fs.data_mapping_root;
if (fs.device_details_root)
sb.device_details_root_ = fs.device_details_root;
patch_space_map_root(sb.metadata_space_map_root_,
fs.metadata_bitmap_root,
fs.metadata_ref_count_root);
patch_space_map_root(sb.data_space_map_root_,
fs.data_bitmap_root,
fs.data_ref_count_root);
write_superblock(bm, sb);
return 0;
}
}
//----------------------------------------------------------------
thin_patch_superblock_cmd::thin_patch_superblock_cmd()
: command("thin_patch_superblock")
{
}
void
thin_patch_superblock_cmd::usage(std::ostream &out) const
{
out << "Usage: " << get_name() << " [options]\n"
<< "Options:\n"
<< " {-h|--help}\n"
<< " {-o|--output} <output device or file>\n"
<< " {--transaction-id} <tid>\n"
<< " {--data-mapping-root} <blocknr>\n"
<< " {--device-details-root} <blocknr>\n"
<< " {--metadata-bitmap-root} <blocknr>\n"
<< " {--metadata-ref-count-root} <blocknr>\n"
<< " {--data-bitmap-root} <blocknr>\n"
<< " {--data-ref-count-root} <blocknr>\n"
<< " {-V|--version}" << endl;
}
int
thin_patch_superblock_cmd::run(int argc, char **argv)
{
int c;
flags fs;
const char shortopts[] = "ho:V";
const struct option longopts[] = {
{ "help", no_argument, NULL, 'h'},
{ "output", required_argument, NULL, 'o'},
{ "transaction-id", required_argument, NULL, 1 },
{ "data-mapping-root", required_argument, NULL, 2 },
{ "device-details-root", required_argument, NULL, 3 },
{ "metadata-bitmap-root", required_argument, NULL, 4 },
{ "metadata-ref-count-root", required_argument, NULL, 5 },
{ "data-bitmap-root", required_argument, NULL, 6 },
{ "data-ref-count-root", required_argument, NULL, 7 },
{ "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.transaction_id = parse_uint64(optarg, "transaction_id");
break;
case 2:
fs.data_mapping_root = parse_uint64(optarg, "data_mapping_root");
break;
case 3:
fs.device_details_root = parse_uint64(optarg, "device_details_root");
break;
case 4:
fs.metadata_bitmap_root = parse_uint64(optarg, "metadata_bitmap_root");
break;
case 5:
fs.metadata_ref_count_root = parse_uint64(optarg, "metadata_ref_count_root");
break;
case 6:
fs.data_bitmap_root = parse_uint64(optarg, "data_bitmap_root");
break;
case 7:
fs.data_ref_count_root = parse_uint64(optarg, "data_ref_count_root");
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 patch_superblock(fs);
}
//----------------------------------------------------------------