diff --git a/persistent-data/data-structures/btree_counter.h b/persistent-data/data-structures/btree_counter.h index 5e07a81..0c79d34 100644 --- a/persistent-data/data-structures/btree_counter.h +++ b/persistent-data/data-structures/btree_counter.h @@ -14,12 +14,14 @@ namespace persistent_data { public: typedef btree tree; - counting_visitor(block_counter &bc, ValueCounter &vc) + counting_visitor(block_counter &bc, ValueCounter &vc, + bool ignore_non_fatal = false) : bc_(bc), vc_(vc), error_outcome_(bc.stop_on_error() ? tree::visitor::RETHROW_EXCEPTION : - tree::visitor::EXCEPTION_HANDLED) { + tree::visitor::EXCEPTION_HANDLED), + ignore_non_fatal_(ignore_non_fatal) { } virtual bool visit_internal(node_location const &l, @@ -66,7 +68,7 @@ namespace persistent_data { if (!checker_.check_block_nr(n) || !checker_.check_value_size(n) || !checker_.check_max_entries(n) || - !checker_.check_nr_entries(n, l.is_sub_root()) || + !check_nr_entries(l, n) || !checker_.check_ordered_keys(n) || !checker_.check_parent_key(n, l.is_sub_root() ? boost::optional() : l.key)) return false; @@ -83,7 +85,7 @@ namespace persistent_data { if (!checker_.check_block_nr(n) || !checker_.check_value_size(n) || !checker_.check_max_entries(n) || - !checker_.check_nr_entries(n, l.is_sub_root()) || + !check_nr_entries(l, n) || !checker_.check_ordered_keys(n) || !checker_.check_parent_key(n, l.is_sub_root() ? boost::optional() : l.key) || !checker_.check_leaf_key(n, last_leaf_key_[l.level()])) @@ -109,11 +111,18 @@ namespace persistent_data { return !seen; } + template + bool check_nr_entries(node_location const &loc, + btree_detail::node_ref const &n) { + return ignore_non_fatal_ || checker_.check_nr_entries(n, loc.is_sub_root()); + } + block_counter &bc_; ValueCounter &vc_; btree_node_checker checker_; boost::optional last_leaf_key_[Levels]; error_outcome error_outcome_; + bool ignore_non_fatal_; }; } @@ -141,8 +150,9 @@ namespace persistent_data { // walked. This walk should only be done once you're sure the tree // is not corrupt. template - void count_btree_blocks(btree const &tree, block_counter &bc, ValueCounter &vc) { - btree_count_detail::counting_visitor v(bc, vc); + void count_btree_blocks(btree const &tree, block_counter &bc, ValueCounter &vc, + bool ignore_non_fatal = false) { + btree_count_detail::counting_visitor v(bc, vc, ignore_non_fatal); tree.visit_depth_first(v); } } diff --git a/thin-provisioning/metadata_checker.cc b/thin-provisioning/metadata_checker.cc index a398ce8..30e5831 100644 --- a/thin-provisioning/metadata_checker.cc +++ b/thin-provisioning/metadata_checker.cc @@ -303,11 +303,12 @@ namespace { error_state check_metadata_space_map_counts(transaction_manager::ptr tm, superblock_detail::superblock const &sb, block_counter &bc, - nested_output &out) { + nested_output &out, + bool ignore_non_fatal) { out << "checking space map counts" << end_message(); nested_output::nest _ = out.push(); - if (!count_metadata(tm, sb, bc)) + if (!count_metadata(tm, sb, bc, false, ignore_non_fatal)) return FATAL; // Finally we need to check the metadata space map agrees @@ -428,7 +429,7 @@ namespace { // if we're checking everything, and there were no errors, // then we should check the space maps too. - err_ << examine_metadata_space_map(tm, sb, options_.sm_opts_, out_, expected_rc_); + err_ << examine_metadata_space_map(tm, sb, options_.sm_opts_, options_.ignore_non_fatal_, out_, expected_rc_); // verify ref-counts of data blocks if (err_ != FATAL && core_sm) @@ -541,13 +542,14 @@ namespace { examine_metadata_space_map(transaction_manager::ptr tm, superblock_detail::superblock const &sb, check_options::space_map_options option, + bool ignore_non_fatal, nested_output &out, block_counter &bc) { error_state err = NO_ERROR; switch (option) { case check_options::SPACE_MAP_FULL: - err << check_metadata_space_map_counts(tm, sb, bc, out); + err << check_metadata_space_map_counts(tm, sb, bc, out, ignore_non_fatal); break; default: break; // do nothing diff --git a/thin-provisioning/metadata_counter.cc b/thin-provisioning/metadata_counter.cc index 9014402..7a40ed1 100644 --- a/thin-provisioning/metadata_counter.cc +++ b/thin-provisioning/metadata_counter.cc @@ -10,14 +10,15 @@ using namespace thin_provisioning; namespace { bool count_trees(transaction_manager::ptr tm, superblock_detail::superblock const &sb, - block_counter &bc) { + block_counter &bc, + bool ignore_non_fatal) { // Count the device tree { noop_value_counter vc; device_tree dtree(*tm, sb.device_details_root_, device_tree_detail::device_details_traits::ref_counter()); - count_btree_blocks(dtree, bc, vc); + count_btree_blocks(dtree, bc, vc, ignore_non_fatal); } // Count the mapping tree @@ -25,7 +26,7 @@ namespace { noop_value_counter vc; mapping_tree mtree(*tm, sb.data_mapping_root_, mapping_tree_detail::block_traits::ref_counter(space_map::ptr())); - count_btree_blocks(mtree, bc, vc); + count_btree_blocks(mtree, bc, vc, ignore_non_fatal); } return true; @@ -65,19 +66,20 @@ namespace { bool thin_provisioning::count_metadata(transaction_manager::ptr tm, superblock_detail::superblock const &sb, block_counter &bc, - bool skip_metadata_snap) { + bool skip_metadata_snap, + bool ignore_non_fatal) { bool ret = true; // Count the superblock bc.inc(superblock_detail::SUPERBLOCK_LOCATION); - ret &= count_trees(tm, sb, bc); + ret &= count_trees(tm, sb, bc, ignore_non_fatal); // Count the metadata snap, if present if (!skip_metadata_snap && sb.metadata_snap_ != superblock_detail::SUPERBLOCK_LOCATION) { bc.inc(sb.metadata_snap_); superblock_detail::superblock snap = read_superblock(tm->get_bm(), sb.metadata_snap_); - ret &= count_trees(tm, snap, bc); + ret &= count_trees(tm, snap, bc, ignore_non_fatal); } ret &= count_space_maps(tm, sb, bc); diff --git a/thin-provisioning/metadata_counter.h b/thin-provisioning/metadata_counter.h index c5916a6..3a38f82 100644 --- a/thin-provisioning/metadata_counter.h +++ b/thin-provisioning/metadata_counter.h @@ -10,7 +10,8 @@ namespace thin_provisioning { bool count_metadata(transaction_manager::ptr tm, superblock_detail::superblock const &sb, block_counter &bc, - bool skip_metadata_snap = false); + bool skip_metadata_snap = false, + bool ignore_non_fatal = false); } //----------------------------------------------------------------