[thin_check] factor out check_space_map_counts()
This commit is contained in:
		@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user