persistent-data/data-structures/btree_counter.h | 22 ++++++++++++++++------ thin-provisioning/metadata_counter.cc | 14 ++++++++------ thin-provisioning/metadata_counter.h | 3 ++- thin-provisioning/thin_check.cc | 2 +- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/persistent-data/data-structures/btree_counter.h b/persistent-data/data-structures/btree_counter.h index 6ccf03a..e639c40 100644 --- a/persistent-data/data-structures/btree_counter.h +++ b/persistent-data/data-structures/btree_counter.h @@ -14,9 +14,11 @@ 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) { + vc_(vc), + ignore_non_fatal_(ignore_non_fatal) { } virtual bool visit_internal(node_location const &l, @@ -63,7 +65,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; @@ -80,7 +82,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()])) @@ -106,10 +108,17 @@ 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]; + bool ignore_non_fatal_; }; } @@ -137,8 +146,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_counter.cc b/thin-provisioning/metadata_counter.cc index 95487d2..6f0d109 100644 --- a/thin-provisioning/metadata_counter.cc +++ b/thin-provisioning/metadata_counter.cc @@ -10,14 +10,15 @@ using namespace thin_provisioning; namespace { void 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); } } @@ -55,17 +56,18 @@ namespace { void 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) { // Count the superblock bc.inc(superblock_detail::SUPERBLOCK_LOCATION); - count_trees(tm, sb, bc); + 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_); - count_trees(tm, snap, bc); + count_trees(tm, snap, bc, ignore_non_fatal); } count_space_maps(tm, sb, bc); diff --git a/thin-provisioning/metadata_counter.h b/thin-provisioning/metadata_counter.h index bc65ab9..ea9813d 100644 --- a/thin-provisioning/metadata_counter.h +++ b/thin-provisioning/metadata_counter.h @@ -10,7 +10,8 @@ namespace thin_provisioning { void 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); } //---------------------------------------------------------------- diff --git a/thin-provisioning/thin_check.cc b/thin-provisioning/thin_check.cc index c2612b5..5900902 100644 --- a/thin-provisioning/thin_check.cc +++ b/thin-provisioning/thin_check.cc @@ -165,7 +165,7 @@ namespace { transaction_manager::ptr tm) { block_counter bc; - count_metadata(tm, sb, bc); + count_metadata(tm, sb, bc, false, fs.ignore_non_fatal_errors); // Finally we need to check the metadata space map agrees // with the counts we've just calculated.