diff --git a/metadata.cc b/metadata.cc index a7da4b9..0f49047 100644 --- a/metadata.cc +++ b/metadata.cc @@ -99,9 +99,9 @@ namespace { } superblock - read_superblock(block_manager<>::ptr bm) { + read_superblock(block_manager<>::ptr bm, block_address location = SUPERBLOCK_LOCATION) { superblock sb; - block_manager<>::read_ref r = bm->read_lock(SUPERBLOCK_LOCATION, + block_manager<>::read_ref r = bm->read_lock(location, mk_validator(new superblock_validator)); superblock_disk const *sbd = reinterpret_cast(&r.data()); superblock_traits::unpack(*sbd, sb); @@ -161,6 +161,20 @@ metadata::metadata(std::string const &dev_path, open_type ot, } } +metadata::metadata(std::string const &dev_path, block_address held_root) +{ + tm_ = open_tm(dev_path, false); + sb_ = read_superblock(tm_->get_bm(), held_root); + // We don't open the metadata sm for a held root + //metadata_sm_ = open_metadata_sm(tm_, &sb_.metadata_space_map_root_); + tm_->set_sm(metadata_sm_); + + data_sm_ = open_disk_sm(tm_, static_cast(&sb_.data_space_map_root_)); + details_ = detail_tree::ptr(new detail_tree(tm_, sb_.device_details_root_, device_details_traits::ref_counter())); + mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_, mtree_ref_counter(tm_))); + mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_, block_time_ref_counter(data_sm_))); +} + namespace { void print_superblock(superblock const &sb) { using namespace std; diff --git a/metadata.h b/metadata.h index 7fbab46..2317027 100644 --- a/metadata.h +++ b/metadata.h @@ -151,6 +151,8 @@ namespace thin_provisioning { sector_t data_block_size = 128, block_address nr_data_blocks = 0); // Only used if CREATE + metadata(std::string const &dev_path, block_address held_root); + void commit(); typedef block_manager<>::read_ref read_ref; diff --git a/metadata_checker.cc b/metadata_checker.cc index ed7a5d1..417a59b 100644 --- a/metadata_checker.cc +++ b/metadata_checker.cc @@ -171,8 +171,22 @@ thin_provisioning::metadata_check(metadata::ptr md) block_counter metadata_counter, data_counter; - if (md->sb_.held_root_) - metadata_counter.inc(md->sb_.held_root_); + if (md->sb_.held_root_) { + block_manager<>::ptr bm = md->tm_->get_bm(); + + + block_address root = md->sb_.held_root_; + + metadata_counter.inc(root); + + superblock sb; + block_manager<>::read_ref r = bm->read_lock(root); + superblock_disk const *sbd = reinterpret_cast(&r.data()); + superblock_traits::unpack(*sbd, sb); + + metadata_counter.inc(sb.data_mapping_root_); + metadata_counter.inc(sb.device_details_root_); + } mapping_validator::ptr mv(new mapping_validator(metadata_counter, data_counter)); diff --git a/metadata_dumper.cc b/metadata_dumper.cc index f73c44a..4a3656f 100644 --- a/metadata_dumper.cc +++ b/metadata_dumper.cc @@ -32,7 +32,7 @@ namespace { mappings_extractor(uint64_t dev_id, emitter::ptr e, space_map::ptr md_sm, space_map::ptr data_sm) : counter_(), - checker_(counter_), + checker_(counter_, false), dev_id_(dev_id), e_(e), md_sm_(md_sm), diff --git a/thin_dump.cc b/thin_dump.cc index 5980e2c..4a85432 100644 --- a/thin_dump.cc +++ b/thin_dump.cc @@ -31,9 +31,12 @@ using namespace std; using namespace thin_provisioning; namespace { - int dump(string const &path, string const &format, bool repair) { + int dump(string const &path, string const &format, bool repair, + block_address held_root = 0) { try { - metadata::ptr md(new metadata(path, metadata::OPEN)); + metadata::ptr md(held_root ? + new metadata(path, held_root) : + new metadata(path, metadata::OPEN)); emitter::ptr e; if (format == "xml") @@ -46,6 +49,7 @@ namespace { } metadata_dump(md, e, repair); + } catch (std::exception &e) { cerr << e.what() << endl; return 1; @@ -60,6 +64,7 @@ namespace { << " {-h|--help}" << endl << " {-f|--format} {xml|human_readable}" << endl << " {-r|--repair}" << endl + << " {-s|--held-superblock}" << endl << " {-V|--version}" << endl; } } @@ -68,10 +73,14 @@ int main(int argc, char **argv) { int c; bool repair = false; - const char shortopts[] = "hf:rV"; + const char shortopts[] = "hs:f:rV"; string format = "xml"; + block_address held_root = 0; + char *end_ptr; + const struct option longopts[] = { { "help", no_argument, NULL, 'h'}, + { "held-root", required_argument, NULL, 's' }, { "format", required_argument, NULL, 'f' }, { "repair", no_argument, NULL, 'r'}, { "version", no_argument, NULL, 'V'}, @@ -92,8 +101,17 @@ int main(int argc, char **argv) repair = true; break; + case 's': + held_root = strtoull(optarg, &end_ptr, 10); + if (end_ptr == optarg) { + cerr << "couldn't parse " << endl; + usage(cerr, basename(argv[0])); + return 1; + } + break; + case 'V': - cout << THIN_PROVISIONING_TOOLS_VERSION << endl; + cerr << THIN_PROVISIONING_TOOLS_VERSION << endl; return 0; default: @@ -108,5 +126,5 @@ int main(int argc, char **argv) return 1; } - return dump(argv[optind], format, repair); + return dump(argv[optind], format, repair, held_root); }