[thin_dump, thin_repair] Fix bad metadata_damage exception

The first pass of the repair process scans all metadata working out the
largest orphan btrees.  This scan doesn't use as much validation as
the btree_walk function which subsequently gets called.

This patch catches any exceptions thrown by the btree walk function
and removes that btree from consideration.
This commit is contained in:
Joe Thornber 2019-05-27 16:06:59 +01:00
parent d299cc66d1
commit 5e6ddbf2da

View File

@ -25,6 +25,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
using namespace boost;
using namespace persistent_data; using namespace persistent_data;
using namespace thin_provisioning; using namespace thin_provisioning;
@ -121,12 +122,19 @@ namespace {
set<uint32_t> dd_; set<uint32_t> dd_;
}; };
set<uint32_t> // See comment on get_map_ids
optional<set<uint32_t> >
get_dev_ids(transaction_manager &tm, block_address root) { get_dev_ids(transaction_manager &tm, block_address root) {
d_thin_id_extractor de; d_thin_id_extractor de;
fatal_details_damage dv; fatal_details_damage dv;
auto tree = device_tree(tm, root, device_tree_detail::device_details_traits::ref_counter()); auto tree = device_tree(tm, root, device_tree_detail::device_details_traits::ref_counter());
try {
walk_device_tree(tree, de, dv); walk_device_tree(tree, de, dv);
} catch (...) {
return optional<set<uint32_t>>();
}
return de.dd_; return de.dd_;
} }
@ -138,12 +146,20 @@ namespace {
set<uint32_t> dd_; set<uint32_t> dd_;
}; };
set<uint32_t> // The walk will do more sanity checks than we did when scanning the metadata, so
// it's possible that it will fail and throw a metadata damage exception.
optional<set<uint32_t> >
get_map_ids(transaction_manager &tm, block_address root) { get_map_ids(transaction_manager &tm, block_address root) {
m_thin_id_extractor me; m_thin_id_extractor me;
fatal_mapping_damage mv; fatal_mapping_damage mv;
auto tree = dev_tree(tm, root, mapping_tree_detail::mtree_traits::ref_counter(tm)); auto tree = dev_tree(tm, root, mapping_tree_detail::mtree_traits::ref_counter(tm));
try {
walk_mapping_tree(tree, me, mv); walk_mapping_tree(tree, me, mv);
} catch (...) {
return optional<set<uint32_t>>();
}
return me.dd_; return me.dd_;
} }
} }
@ -340,12 +356,18 @@ namespace {
sort(pairs.begin(), pairs.end(), cmp_time_counts); sort(pairs.begin(), pairs.end(), cmp_time_counts);
map<block_address, set<uint32_t>> ds; map<block_address, set<uint32_t>> ds;
for (auto b : d_roots) for (auto b : d_roots) {
ds.insert(make_pair(b, get_dev_ids(tm, b))); auto maybe_ids = get_dev_ids(tm, b);
if (maybe_ids)
ds.insert(make_pair(b, *maybe_ids));
}
map<block_address, set<uint32_t>> ms; map<block_address, set<uint32_t>> ms;
for (auto b : m_roots) for (auto b : m_roots) {
ms.insert(make_pair(b, get_map_ids(tm, b))); auto maybe_ids = get_map_ids(tm, b);
if (maybe_ids)
ms.insert(make_pair(b, *maybe_ids));
}
// now we check that the thin_ids are identical // now we check that the thin_ids are identical
vector<pair<block_address, block_address>> filtered; vector<pair<block_address, block_address>> filtered;