Blob Blame History Raw
 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<Levels, ValueTraits> 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<uint64_t>() : 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<uint64_t>() : l.key) ||
 				    !checker_.check_leaf_key(n, last_leaf_key_[l.level()]))
@@ -106,10 +108,17 @@ namespace persistent_data {
 				return !seen;
 			}
 
+			template <typename ValueTraits2>
+			bool check_nr_entries(node_location const &loc,
+					      btree_detail::node_ref<ValueTraits2> 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<uint64_t> 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 <unsigned Levels, typename ValueTraits, typename ValueCounter>
-	void count_btree_blocks(btree<Levels, ValueTraits> const &tree, block_counter &bc, ValueCounter &vc) {
-		btree_count_detail::counting_visitor<Levels, ValueTraits, ValueCounter> v(bc, vc);
+	void count_btree_blocks(btree<Levels, ValueTraits> const &tree, block_counter &bc, ValueCounter &vc,
+				bool ignore_non_fatal = false) {
+		btree_count_detail::counting_visitor<Levels, ValueTraits, ValueCounter> 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<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_btree_blocks(dtree, bc, vc, ignore_non_fatal);
 		}
 
 		// Count the mapping tree
@@ -25,7 +26,7 @@ namespace {
 			noop_value_counter<mapping_tree_detail::block_time> 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.