[block_counter] Add the stop-on-error option to prevent silent errors

The stop-on-error option aims to solve the lack of damage_visitor support
in space_map::count_metadata and btree counting_visitor. To prevent
possibly silent errors during space map or btree counting, the option
stops the counting process immediately when a btree or bitmap error
was found.

The bitmap blocks are also validated to avoid potential false-alarm,
if broken bitmap is not counted, and the corresponding ref-count is
also zeroed.
This commit is contained in:
Ming-Hung Tsai 2020-08-11 19:41:41 +08:00
parent 3609b8bee5
commit 12725983db
3 changed files with 46 additions and 10 deletions

View File

@ -33,6 +33,12 @@ namespace persistent_data {
public: public:
typedef std::map<block_address, unsigned> count_map; typedef std::map<block_address, unsigned> count_map;
block_counter(): stop_on_error_(false) {}
block_counter(bool stop_on_error)
: stop_on_error_(stop_on_error) {
}
virtual ~block_counter() {} virtual ~block_counter() {}
virtual void inc(block_address b) { virtual void inc(block_address b) {
@ -52,8 +58,13 @@ namespace persistent_data {
return counts_; return counts_;
} }
virtual bool stop_on_error() {
return stop_on_error_;
}
private: private:
count_map counts_; count_map counts_;
bool stop_on_error_;
}; };
//---------------------------------------------------------------- //----------------------------------------------------------------

View File

@ -16,7 +16,10 @@ namespace persistent_data {
counting_visitor(block_counter &bc, ValueCounter &vc) counting_visitor(block_counter &bc, ValueCounter &vc)
: bc_(bc), : bc_(bc),
vc_(vc) { vc_(vc),
error_outcome_(bc.stop_on_error() ?
tree::visitor::RETHROW_EXCEPTION :
tree::visitor::EXCEPTION_HANDLED) {
} }
virtual bool visit_internal(node_location const &l, virtual bool visit_internal(node_location const &l,
@ -51,7 +54,7 @@ namespace persistent_data {
error_outcome error_accessing_node(node_location const &l, block_address b, error_outcome error_accessing_node(node_location const &l, block_address b,
std::string const &what) { std::string const &what) {
return btree<Levels, ValueTraits>::visitor::EXCEPTION_HANDLED; return error_outcome_;
} }
private: private:
@ -110,6 +113,7 @@ namespace persistent_data {
ValueCounter &vc_; ValueCounter &vc_;
btree_node_checker checker_; btree_node_checker checker_;
boost::optional<uint64_t> last_leaf_key_[Levels]; boost::optional<uint64_t> last_leaf_key_[Levels];
error_outcome error_outcome_;
}; };
} }

View File

@ -639,21 +639,30 @@ namespace {
//-------------------------------- //--------------------------------
struct index_entry_counter { struct index_entry_counter {
index_entry_counter(block_counter &bc) index_entry_counter(transaction_manager &tm,
: bc_(bc) { block_counter &bc)
: tm_(tm),
bc_(bc),
bitmap_validator_(new bitmap_block_validator()) {
} }
void visit(btree_detail::node_location const &loc, index_entry const &ie) { void visit(btree_detail::node_location const &loc, index_entry const &ie) {
if (ie.blocknr_ != 0) if (!ie.blocknr_)
return;
block_manager::read_ref rr = tm_.read_lock(ie.blocknr_, bitmap_validator_);
if (rr.data())
bc_.inc(ie.blocknr_); bc_.inc(ie.blocknr_);
} }
private: private:
transaction_manager &tm_;
block_counter &bc_; block_counter &bc_;
bcache::validator::ptr bitmap_validator_;
}; };
virtual void count_metadata(block_counter &bc) const { virtual void count_metadata(block_counter &bc) const {
index_entry_counter vc(bc); index_entry_counter vc(tm_, bc);
count_btree_blocks(bitmaps_, bc, vc); count_btree_blocks(bitmaps_, bc, vc);
} }
@ -705,14 +714,16 @@ namespace {
typedef std::shared_ptr<metadata_index_store> ptr; typedef std::shared_ptr<metadata_index_store> ptr;
metadata_index_store(transaction_manager &tm) metadata_index_store(transaction_manager &tm)
: tm_(tm) { : tm_(tm),
bitmap_validator_(new bitmap_block_validator()) {
block_manager::write_ref wr = tm_.new_block(index_validator()); block_manager::write_ref wr = tm_.new_block(index_validator());
bitmap_root_ = wr.get_location(); bitmap_root_ = wr.get_location();
} }
metadata_index_store(transaction_manager &tm, block_address root, block_address nr_indexes) metadata_index_store(transaction_manager &tm, block_address root, block_address nr_indexes)
: tm_(tm), : tm_(tm),
bitmap_root_(root) { bitmap_root_(root),
bitmap_validator_(new bitmap_block_validator()) {
resize(nr_indexes); resize(nr_indexes);
load_ies(); load_ies();
} }
@ -723,8 +734,17 @@ namespace {
for (unsigned i = 0; i < entries_.size(); i++) { for (unsigned i = 0; i < entries_.size(); i++) {
block_address b = entries_[i].blocknr_; block_address b = entries_[i].blocknr_;
if (b != 0) if (b == 0)
continue;
try {
block_manager::read_ref rr = tm_.read_lock(b, bitmap_validator_);
if (rr.data())
bc.inc(b); bc.inc(b);
} catch (std::exception &e) {
if (bc.stop_on_error())
throw;
}
} }
} }
@ -786,6 +806,7 @@ namespace {
transaction_manager &tm_; transaction_manager &tm_;
block_address bitmap_root_; block_address bitmap_root_;
std::vector<index_entry> entries_; std::vector<index_entry> entries_;
bcache::validator::ptr bitmap_validator_;
}; };
} }