238 lines
6.4 KiB
C++
Raw Normal View History

2011-12-15 19:34:31 +01:00
// Copyright (C) 2011 Red Hat, Inc. All rights reserved.
2011-12-06 13:53:05 +00:00
//
2011-12-06 13:43:56 +00:00
// 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/>.
2011-10-28 12:13:03 +01:00
#include "metadata_dumper.h"
2013-05-20 17:37:46 +01:00
#include "thin-provisioning/mapping_tree.h"
2011-10-10 14:10:30 +01:00
using namespace persistent_data;
using namespace thin_provisioning;
//----------------------------------------------------------------
namespace {
2013-05-20 17:37:46 +01:00
class mappings_extractor : public mapping_tree::visitor {
2011-10-10 14:10:30 +01:00
public:
typedef boost::shared_ptr<mappings_extractor> ptr;
typedef btree_detail::node_location node_location;
2013-05-20 17:37:46 +01:00
typedef btree_checker<2, mapping_tree_detail::block_traits> checker;
2011-10-10 14:10:30 +01:00
mappings_extractor(uint64_t dev_id, emitter::ptr e,
space_map::ptr md_sm, space_map::ptr data_sm)
2012-03-02 10:00:31 +00:00
: counter_(),
2012-05-17 12:28:23 +01:00
checker_(counter_, false),
2012-03-02 10:00:31 +00:00
dev_id_(dev_id),
2011-10-10 14:10:30 +01:00
e_(e),
md_sm_(md_sm),
data_sm_(data_sm),
2012-03-02 10:00:31 +00:00
in_range_(false),
2013-08-15 16:26:17 +01:00
time_(),
2012-03-02 10:00:31 +00:00
found_errors_(false) {
2011-10-10 14:10:30 +01:00
}
bool visit_internal(node_location const &loc,
btree_detail::node_ref<block_traits> const &n) {
2012-03-02 10:00:31 +00:00
if (!checker_.visit_internal(loc, n)) {
2012-03-02 10:00:31 +00:00
found_errors_ = true;
return false;
}
2013-06-28 14:24:39 +01:00
return (loc.is_sub_root() && loc.path.size()) ? (loc.path[0] == dev_id_) : true;
2011-10-10 14:10:30 +01:00
}
bool visit_internal_leaf(node_location const &loc,
btree_detail::node_ref<block_traits> const &n) {
if (!checker_.visit_internal_leaf(loc, n)) {
2012-03-02 10:00:31 +00:00
found_errors_ = true;
return false;
}
2011-10-10 14:10:30 +01:00
return true;
}
bool visit_leaf(node_location const &loc,
2013-05-20 17:37:46 +01:00
btree_detail::node_ref<mapping_tree_detail::block_traits> const &n) {
if (!checker_.visit_leaf(loc, n)) {
2012-03-02 10:00:31 +00:00
found_errors_ = true;
return false;
}
if (loc.path[0] == dev_id_)
for (unsigned i = 0; i < n.get_nr_entries(); i++) {
mapping_tree_detail::block_time bt = n.value_at(i);
add_mapping(n.key_at(i), bt.block_, bt.time_);
}
2011-10-10 14:10:30 +01:00
return true;
}
void visit_complete() {
end_mapping();
}
2012-03-02 10:00:31 +00:00
bool corruption() const {
return !checker_.get_errors()->empty();
}
2011-10-10 14:10:30 +01:00
private:
void start_mapping(uint64_t origin_block, uint64_t dest_block, uint32_t time) {
2011-10-10 14:10:30 +01:00
origin_start_ = origin_block;
dest_start_ = dest_block;
time_ = time;
2011-10-10 14:10:30 +01:00
len_ = 1;
in_range_ = true;
}
void end_mapping() {
if (in_range_) {
if (len_ == 1)
e_->single_map(origin_start_, dest_start_, time_);
2011-10-10 14:10:30 +01:00
else
e_->range_map(origin_start_, dest_start_, time_, len_);
2011-10-10 14:10:30 +01:00
in_range_ = false;
}
}
void add_mapping(uint64_t origin_block, uint64_t dest_block, uint32_t time) {
2011-10-10 14:10:30 +01:00
if (!in_range_)
start_mapping(origin_block, dest_block, time);
2011-10-10 14:10:30 +01:00
else if (origin_block == origin_start_ + len_ &&
dest_block == dest_start_ + len_ &&
time == time_)
2011-10-10 14:10:30 +01:00
len_++;
else {
end_mapping();
start_mapping(origin_block, dest_block, time);
2011-10-10 14:10:30 +01:00
}
}
2012-03-02 10:00:31 +00:00
// Declaration order of counter_ and checker_ is important.
block_counter counter_;
checker checker_;
2011-10-10 14:10:30 +01:00
uint64_t dev_id_;
emitter::ptr e_;
space_map::ptr md_sm_;
space_map::ptr data_sm_;
bool in_range_;
uint64_t origin_start_, dest_start_, len_;
uint32_t time_;
2012-03-02 10:00:31 +00:00
bool found_errors_;
2011-10-10 14:10:30 +01:00
};
class details_extractor : public btree<1, device_tree_detail::device_details_traits>::visitor {
2011-10-10 14:10:30 +01:00
public:
typedef btree<1, device_tree_detail::device_details_traits>::visitor::node_location node_location;
2011-10-10 14:10:30 +01:00
typedef boost::shared_ptr<details_extractor> ptr;
typedef btree_checker<1, device_tree_detail::device_details_traits> checker;
2011-10-10 14:10:30 +01:00
2012-03-02 10:00:31 +00:00
details_extractor()
: counter_(),
checker_(counter_, false) {
2011-10-10 14:10:30 +01:00
}
bool visit_internal(node_location const &loc,
btree_detail::node_ref<block_traits> const &n) {
return checker_.visit_internal(loc, n);
2011-10-10 14:10:30 +01:00
}
bool visit_internal_leaf(node_location const &loc,
btree_detail::node_ref<block_traits> const &n) {
return checker_.visit_internal_leaf(loc, n);
2011-10-10 14:10:30 +01:00
}
bool visit_leaf(node_location const &loc,
btree_detail::node_ref<device_tree_detail::device_details_traits> const &n) {
if (!checker_.visit_leaf(loc, n))
2012-03-02 10:00:31 +00:00
return false;
2011-10-10 14:10:30 +01:00
for (unsigned i = 0; i < n.get_nr_entries(); i++)
devices_.insert(make_pair(n.key_at(i), n.value_at(i)));
return true;
}
map<uint64_t, device_tree_detail::device_details> const &get_devices() const {
2011-10-10 14:10:30 +01:00
return devices_;
}
2012-03-02 10:00:31 +00:00
bool corruption() const {
return !checker_.get_errors()->empty();
}
2011-10-10 14:10:30 +01:00
private:
2012-03-02 10:00:31 +00:00
// Declaration order of counter_ and checker_ is important.
block_counter counter_;
checker checker_;
map<uint64_t, device_tree_detail::device_details> devices_;
2011-10-10 14:10:30 +01:00
};
}
2011-10-28 12:13:03 +01:00
//----------------------------------------------------------------
2011-10-10 14:10:30 +01:00
void
2012-03-02 10:00:31 +00:00
thin_provisioning::metadata_dump(metadata::ptr md, emitter::ptr e, bool repair)
2011-10-10 14:10:30 +01:00
{
2013-06-25 13:48:02 +01:00
boost::optional<uint64_t> md_snap = md->sb_.metadata_snap_ ?
boost::optional<uint64_t>(md->sb_.metadata_snap_) :
boost::optional<uint64_t>();
e->begin_superblock("", md->sb_.time_,
md->sb_.trans_id_,
md->sb_.data_block_size_,
md->data_sm_->get_nr_blocks(),
md_snap);
2011-10-10 16:14:36 +01:00
details_extractor de;
md->details_->visit_depth_first(de);
if (de.corruption() && !repair)
2012-03-02 10:00:31 +00:00
throw runtime_error("corruption in device details tree");
map<uint64_t, device_tree_detail::device_details> const &devs = de.get_devices();
2011-10-10 14:10:30 +01:00
map<uint64_t, device_tree_detail::device_details>::const_iterator it, end = devs.end();
2011-10-10 14:10:30 +01:00
for (it = devs.begin(); it != end; ++it) {
uint64_t dev_id = it->first;
device_tree_detail::device_details const &dd = it->second;
2011-10-10 14:10:30 +01:00
e->begin_device(dev_id,
dd.mapped_blocks_,
dd.transaction_id_,
dd.creation_time_,
dd.snapshotted_time_);
mappings_extractor me(dev_id, e, md->metadata_sm_, md->data_sm_);
md->mappings_->visit_depth_first(me);
2011-10-10 14:10:30 +01:00
if (me.corruption() && !repair) {
2012-03-02 10:00:31 +00:00
ostringstream out;
out << "corruption in mappings for device " << dev_id;
throw runtime_error(out.str());
}
2011-10-10 14:10:30 +01:00
e->end_device();
}
2011-10-10 16:14:36 +01:00
e->end_superblock();
2011-10-10 14:10:30 +01:00
}
//----------------------------------------------------------------