[metadata_counter] Count under populated nodes if the option is provided
This commit is contained in:
		| @@ -14,12 +14,14 @@ 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), | ||||
| 				  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<uint64_t>() : 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<uint64_t>() : l.key) || | ||||
| 				    !checker_.check_leaf_key(n, last_leaf_key_[l.level()])) | ||||
| @@ -109,11 +111,18 @@ 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]; | ||||
| 			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 <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); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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<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); | ||||
| 		} | ||||
|  | ||||
| 		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); | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|   | ||||
		Reference in New Issue
	
	Block a user