[thin_check] factor out check_space_map_counts()

This commit is contained in:
Joe Thornber 2015-04-08 14:07:38 +01:00
parent a934ee69c4
commit 270c0f7041

View File

@ -41,8 +41,6 @@ using namespace thin_provisioning;
//----------------------------------------------------------------
namespace {
//--------------------------------
block_manager<>::ptr
open_bm(string const &path) {
block_address nr_blocks = get_nr_blocks(path);
@ -73,7 +71,7 @@ namespace {
nested_output::nest _ = out_.push();
out_ << d.desc_ << end_message();
}
err_ = combine_errors(err_, FATAL);
err_ << FATAL;
}
base::error_state get_error() const {
@ -101,7 +99,7 @@ namespace {
out_ << d.desc_ << end_message();
}
err_ = combine_errors(err_, FATAL);
err_ << FATAL;
}
error_state get_error() const {
@ -128,7 +126,7 @@ namespace {
nested_output::nest _ = out_.push();
out_ << d.desc_ << end_message();
}
err_ = combine_errors(err_, FATAL);
err_ << FATAL;
}
virtual void visit(mapping_tree_detail::missing_mappings const &d) {
@ -137,7 +135,7 @@ namespace {
nested_output::nest _ = out_.push();
out_ << d.desc_ << end_message();
}
err_ = combine_errors(err_, FATAL);
err_ << FATAL;
}
error_state get_error() const {
@ -171,6 +169,77 @@ namespace {
bool clear_needs_check_flag_on_success;
};
error_state check_space_map_counts(flags const &fs, nested_output &out,
superblock_detail::superblock &sb,
block_manager<>::ptr bm,
transaction_manager::ptr tm) {
block_counter bc;
// Count the superblock
bc.inc(superblock_detail::SUPERBLOCK_LOCATION);
// Count the metadata snap, if present
if (sb.metadata_snap_ != superblock_detail::SUPERBLOCK_LOCATION) {
bc.inc(sb.metadata_snap_);
superblock_detail::superblock snap = read_superblock(bm, sb.metadata_snap_);
bc.inc(snap.data_mapping_root_);
bc.inc(snap.device_details_root_);
}
// Count the device tree
{
noop_value_counter<device_tree_detail::device_details> vc;
device_tree dtree(*tm, sb.device_details_root_,
device_tree_detail::device_details_traits::ref_counter());
count_btree_blocks(dtree, bc, vc);
}
// Count the mapping tree
{
noop_value_counter<mapping_tree_detail::block_time> vc;
mapping_tree mtree(*tm, sb.data_mapping_root_,
mapping_tree_detail::block_traits::ref_counter(tm->get_sm()));
count_btree_blocks(mtree, bc, vc);
}
// Count the metadata space map
{
persistent_space_map::ptr metadata_sm =
open_metadata_sm(*tm, static_cast<void *>(&sb.metadata_space_map_root_));
metadata_sm->count_metadata(bc);
}
// Count the data space map
{
persistent_space_map::ptr data_sm =
open_disk_sm(*tm, static_cast<void *>(&sb.data_space_map_root_));
data_sm->count_metadata(bc);
}
// Finally we need to check the metadata space map agrees
// with the counts we've just calculated.
error_state err = NO_ERROR;
nested_output::nest _ = out.push();
persistent_space_map::ptr metadata_sm =
open_metadata_sm(*tm, static_cast<void *>(&sb.metadata_space_map_root_));
for (unsigned b = 0; b < metadata_sm->get_nr_blocks(); b++) {
ref_t c_actual = metadata_sm->get_count(b);
ref_t c_expected = bc.get_count(b);
if (c_actual != c_expected) {
out << "metadata reference counts differ for block " << b
<< ", expected " << c_expected
<< ", but got " << c_actual
<< end_message();
err << (c_actual > c_expected ? NON_FATAL : FATAL);
}
}
return err;
}
error_state metadata_check(string const &path, flags fs) {
block_manager<>::ptr bm = open_bm(path);
@ -223,85 +292,17 @@ namespace {
}
}
error_state mplus_err = combine_errors(sb_rep.get_error(),
combine_errors(mapping_rep.get_error(),
dev_rep.get_error()));
error_state err = NO_ERROR;
err << sb_rep.get_error() << mapping_rep.get_error() << dev_rep.get_error();
// if we're checking everything, and there were no errors,
// then we should check the space maps too.
if (fs.check_device_tree && fs.check_mapping_tree_level2 && mplus_err == NO_ERROR) {
if (fs.check_device_tree && fs.check_mapping_tree_level2 && err != FATAL) {
out << "checking space map counts" << end_message();
{
nested_output::nest _ = out.push();
block_counter bc;
// Count the superblock
bc.inc(superblock_detail::SUPERBLOCK_LOCATION);
// Count the metadata snap, if present
if (sb.metadata_snap_ != superblock_detail::SUPERBLOCK_LOCATION) {
bc.inc(sb.metadata_snap_);
superblock_detail::superblock snap = read_superblock(bm, sb.metadata_snap_);
bc.inc(snap.data_mapping_root_);
bc.inc(snap.device_details_root_);
}
// Count the device tree
{
noop_value_counter<device_tree_detail::device_details> vc;
device_tree dtree(*tm, sb.device_details_root_,
device_tree_detail::device_details_traits::ref_counter());
count_btree_blocks(dtree, bc, vc);
}
// Count the mapping tree
{
noop_value_counter<mapping_tree_detail::block_time> vc;
mapping_tree mtree(*tm, sb.data_mapping_root_,
mapping_tree_detail::block_traits::ref_counter(tm->get_sm()));
count_btree_blocks(mtree, bc, vc);
}
// Count the metadata space map
{
persistent_space_map::ptr metadata_sm =
open_metadata_sm(*tm, static_cast<void *>(&sb.metadata_space_map_root_));
metadata_sm->count_metadata(bc);
}
// Count the data space map
{
persistent_space_map::ptr data_sm =
open_disk_sm(*tm, static_cast<void *>(&sb.data_space_map_root_));
data_sm->count_metadata(bc);
}
// Finally we need to check the metadata
// space map agrees with the counts we've
// just calculated.
{
persistent_space_map::ptr metadata_sm =
open_metadata_sm(*tm, static_cast<void *>(&sb.metadata_space_map_root_));
for (unsigned b = 0; b < metadata_sm->get_nr_blocks(); b++) {
ref_t c_actual = metadata_sm->get_count(b);
ref_t c_expected = bc.get_count(b);
if (c_actual != c_expected) {
out << "metadata reference counts differ for block " << b
<< ", expected " << c_expected
<< ", but got " << c_actual
<< end_message();
mplus_err = combine_errors(mplus_err,
c_actual > c_expected ? NON_FATAL : FATAL);
}
}
}
}
err << check_space_map_counts(fs, out, sb, bm, tm);
}
return mplus_err;
return err;
}
void clear_needs_check(string const &path) {