Working on device_checker

This commit is contained in:
Joe Thornber 2013-04-29 15:37:53 +01:00
parent 524f9474cf
commit 969a5f62c6
5 changed files with 164 additions and 109 deletions

View File

@ -1,19 +1,103 @@
#include "thin-provisioning/device_checker.h" #include "thin-provisioning/device_checker.h"
#include "persistent-data/data-structures/btree_checker.h"
#include "persistent-data/transaction_manager.h"
#include "persistent-data/space-maps/core.h"
#include "thin-provisioning/metadata.h"
#include "thin-provisioning/metadata_disk_structures.h"
using namespace persistent_data;
using namespace thin_provisioning; using namespace thin_provisioning;
//---------------------------------------------------------------- //----------------------------------------------------------------
device_checker::device_checker(block_manager::ptr bm) namespace {
: checker(bm) // FIXME: duplication with metadata.cc
transaction_manager::ptr
open_tm(block_manager<>::ptr bm) {
space_map::ptr sm(new core_map(bm->get_nr_blocks()));
sm->inc(SUPERBLOCK_LOCATION);
transaction_manager::ptr tm(new transaction_manager(bm, sm));
return tm;
}
class device_visitor : public btree<1, device_details_traits>::visitor {
public:
typedef boost::shared_ptr<device_visitor> ptr;
typedef btree_checker<1, device_details_traits> checker;
device_visitor(block_counter &counter)
: checker_(counter) {
}
bool visit_internal(unsigned level,
bool sub_root,
optional<uint64_t> key,
btree_detail::node_ref<uint64_traits> const &n) {
return checker_.visit_internal(level, sub_root, key, n);
}
bool visit_internal_leaf(unsigned level,
bool sub_root,
optional<uint64_t> key,
btree_detail::node_ref<uint64_traits> const &n) {
return checker_.visit_internal_leaf(level, sub_root, key, n);
}
bool visit_leaf(unsigned level,
bool sub_root,
optional<uint64_t> key,
btree_detail::node_ref<device_details_traits> const &n) {
if (!checker_.visit_leaf(level, sub_root, key, n))
return false;
for (unsigned i = 0; i < n.get_nr_entries(); i++)
devices_.insert(n.key_at(i));
return true;
}
set<uint64_t> const &get_devices() const {
return devices_;
}
private:
checker checker_;
set<uint64_t> devices_;
};
}
//----------------------------------------------------------------
device_checker::device_checker(block_manager::ptr bm,
block_address root)
: checker(bm),
root_(root)
{ {
} }
damage_list_ptr damage_list_ptr
device_checker::check() device_checker::check()
{ {
// FIXME: finish. block_counter counter;
return damage_list_ptr(new damage_list); device_visitor::ptr v(new device_visitor(counter));
transaction_manager::ptr tm(open_tm(bm_));
detail_tree::ptr details(new detail_tree(tm, root_,
device_details_traits::ref_counter()));
damage_list_ptr damage(new damage_list);
try {
details->visit(v);
} catch (std::exception const &e) {
metadata_damage::ptr d(new missing_device_details(range64()));
damage->push_back(d);
}
return damage;
} }
//---------------------------------------------------------------- //----------------------------------------------------------------

View File

@ -8,8 +8,11 @@
namespace thin_provisioning { namespace thin_provisioning {
class device_checker : public checker { class device_checker : public checker {
public: public:
device_checker(block_manager::ptr bm); device_checker(block_manager::ptr bm, block_address btree_root);
damage_list_ptr check(); damage_list_ptr check();
private:
block_address root_;
}; };
} }

View File

@ -48,10 +48,8 @@ super_block_corruption::visit(metadata_damage_visitor &visitor) const
//-------------------------------- //--------------------------------
missing_device_details::missing_device_details(uint64_t missing_begin, missing_device_details::missing_device_details(range64 missing)
uint64_t missing_end) : missing_(missing)
: missing_begin_(missing_begin),
missing_end_(missing_end)
{ {
} }
@ -63,10 +61,8 @@ missing_device_details::visit(metadata_damage_visitor &visitor) const
//-------------------------------- //--------------------------------
missing_devices::missing_devices(uint64_t missing_begin, missing_devices::missing_devices(range64 missing)
uint64_t missing_end) : missing_(missing)
: missing_begin_(missing_begin),
missing_end_(missing_end)
{ {
} }
@ -78,12 +74,9 @@ missing_devices::visit(metadata_damage_visitor &visitor) const
//-------------------------------- //--------------------------------
missing_mappings::missing_mappings(uint64_t dev, missing_mappings::missing_mappings(uint64_t dev, range64 missing)
uint64_t missing_begin,
uint64_t missing_end)
: dev_(dev), : dev_(dev),
missing_begin_(missing_begin), missing_(missing)
missing_end_(missing_end)
{ {
} }
@ -129,10 +122,8 @@ bad_data_ref_count::visit(metadata_damage_visitor &visitor) const
//-------------------------------- //--------------------------------
missing_metadata_ref_counts::missing_metadata_ref_counts(block_address missing_begin, missing_metadata_ref_counts::missing_metadata_ref_counts(range64 missing)
block_address missing_end) : missing_(missing)
: missing_begin_(missing_begin),
missing_end_(missing_end)
{ {
} }
@ -144,10 +135,8 @@ missing_metadata_ref_counts::visit(metadata_damage_visitor &visitor) const
//-------------------------------- //--------------------------------
missing_data_ref_counts::missing_data_ref_counts(block_address missing_begin, missing_data_ref_counts::missing_data_ref_counts(range64 missing)
block_address missing_end) : missing_(missing)
: missing_begin_(missing_begin),
missing_end_(missing_end)
{ {
} }
@ -236,52 +225,6 @@ namespace {
set<uint64_t> devices_; set<uint64_t> devices_;
}; };
class details_validator : public btree<1, device_details_traits>::visitor {
public:
typedef boost::shared_ptr<details_validator> ptr;
typedef btree_checker<1, device_details_traits> checker;
details_validator(block_counter &counter)
: checker_(counter) {
}
bool visit_internal(unsigned level,
bool sub_root,
optional<uint64_t> key,
btree_detail::node_ref<uint64_traits> const &n) {
return checker_.visit_internal(level, sub_root, key, n);
}
bool visit_internal_leaf(unsigned level,
bool sub_root,
optional<uint64_t> key,
btree_detail::node_ref<uint64_traits> const &n) {
return checker_.visit_internal_leaf(level, sub_root, key, n);
}
bool visit_leaf(unsigned level,
bool sub_root,
optional<uint64_t> key,
btree_detail::node_ref<device_details_traits> const &n) {
if (!checker_.visit_leaf(level, sub_root, key, n))
return false;
for (unsigned i = 0; i < n.get_nr_entries(); i++)
devices_.insert(n.key_at(i));
return true;
}
set<uint64_t> const &get_devices() const {
return devices_;
}
private:
checker checker_;
set<uint64_t> devices_;
};
struct check_count : public space_map::iterator { struct check_count : public space_map::iterator {
check_count(string const &desc, block_counter const &expected) check_count(string const &desc, block_counter const &expected)
: bad_(false), : bad_(false),

View File

@ -23,6 +23,8 @@
#include "persistent-data/error_set.h" #include "persistent-data/error_set.h"
#include "persistent-data/space_map.h" #include "persistent-data/space_map.h"
#include "thin-provisioning/range.h"
#include <deque> #include <deque>
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -53,36 +55,28 @@ namespace thin_provisioning {
void visit(metadata_damage_visitor &visitor) const; void visit(metadata_damage_visitor &visitor) const;
}; };
struct missing_device_details : public metadata_damage { typedef range<uint64_t> range64;
missing_device_details(uint64_t missing_begin,
uint64_t missing_end);
struct missing_device_details : public metadata_damage {
missing_device_details(range64 missing);
virtual void visit(metadata_damage_visitor &visitor) const; virtual void visit(metadata_damage_visitor &visitor) const;
uint64_t missing_begin_; range64 missing_;
uint64_t missing_end_;
}; };
struct missing_devices : public metadata_damage { struct missing_devices : public metadata_damage {
missing_devices(uint64_t missing_begin, missing_devices(range64 missing);
uint64_t missing_end);
virtual void visit(metadata_damage_visitor &visitor) const; virtual void visit(metadata_damage_visitor &visitor) const;
uint64_t missing_begin_; range64 missing_;
uint64_t missing_end_;
}; };
struct missing_mappings : public metadata_damage { struct missing_mappings : public metadata_damage {
missing_mappings(uint64_t dev, missing_mappings(uint64_t dev, range64 missing);
uint64_t missing_begin,
uint64_t missing_end);
virtual void visit(metadata_damage_visitor &visitor) const; virtual void visit(metadata_damage_visitor &visitor) const;
uint64_t dev_; uint64_t dev_;
uint64_t missing_begin_; range64 missing_;
uint64_t missing_end_;
}; };
struct bad_metadata_ref_count : public metadata_damage { struct bad_metadata_ref_count : public metadata_damage {
@ -110,23 +104,17 @@ namespace thin_provisioning {
}; };
struct missing_metadata_ref_counts : public metadata_damage { struct missing_metadata_ref_counts : public metadata_damage {
missing_metadata_ref_counts(block_address missing_begin, missing_metadata_ref_counts(range64 missing);
block_address missing_end);
virtual void visit(metadata_damage_visitor &visitor) const; virtual void visit(metadata_damage_visitor &visitor) const;
block_address missing_begin_; range64 missing_;
block_address missing_end_;
}; };
struct missing_data_ref_counts : public metadata_damage { struct missing_data_ref_counts : public metadata_damage {
missing_data_ref_counts(block_address missing_begin, missing_data_ref_counts(range64 missing);
block_address missing_end);
virtual void visit(metadata_damage_visitor &visitor) const; virtual void visit(metadata_damage_visitor &visitor) const;
block_address missing_begin_; range64 missing_;
block_address missing_end_;
}; };
class metadata_damage_visitor { class metadata_damage_visitor {

View File

@ -6,6 +6,7 @@
#include "thin-provisioning/device_checker.h" #include "thin-provisioning/device_checker.h"
#include "thin-provisioning/restore_emitter.h" #include "thin-provisioning/restore_emitter.h"
#include "thin-provisioning/superblock_checker.h" #include "thin-provisioning/superblock_checker.h"
#include "thin-provisioning/superblock_validator.h"
#include <unistd.h> #include <unistd.h>
@ -122,24 +123,29 @@ namespace {
builder.build(); builder.build();
} }
superblock read_superblock() {
superblock sb;
block_manager<>::read_ref r = bm_->read_lock(SUPERBLOCK_LOCATION, superblock_validator());
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(&r.data());
superblock_traits::unpack(*sbd, sb);
return sb;
}
void zero_block(block_address b) {
::test::zero_block(bm_, b);
}
with_temp_directory dir_; with_temp_directory dir_;
block_manager<>::ptr bm_; block_manager<>::ptr bm_;
}; };
class SuperBlockCheckerTests : public MetadataCheckerTests { class SuperBlockCheckerTests : public MetadataCheckerTests {
public: public:
void corrupt_superblock() { void corrupt_superblock() {
zero_block(bm_, SUPERBLOCK_LOCATION); zero_block(SUPERBLOCK_LOCATION);
} }
}; };
//--------------------------------
class DevicesCheckerTests : public MetadataCheckerTests {
public:
};
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -170,9 +176,40 @@ TEST_F(SuperBlockCheckerTests, fails_with_bad_checksum)
//---------------------------------------------------------------- //----------------------------------------------------------------
TEST_F(DevicesCheckerTests, create_require_a_block_manager) namespace {
class DeviceCheckerTests : public MetadataCheckerTests {
public:
DeviceCheckerTests() {
}
block_address devices_root() {
superblock sb = read_superblock();
return sb.device_details_root_;
}
device_checker::ptr mk_checker() {
return device_checker::ptr(new device_checker(bm_, devices_root()));
}
};
}
TEST_F(DeviceCheckerTests, create_require_a_block_manager_and_a_root_block)
{ {
device_checker dc(bm_); mk_checker();
}
TEST_F(DeviceCheckerTests, passes_with_valid_metadata_and_zero_devices)
{
damage_list_ptr damage = mk_checker()->check();
ASSERT_THAT(damage->size(), Eq(0u));
}
TEST_F(DeviceCheckerTests, fails_with_corrupt_root)
{
zero_block(devices_root());
damage_list_ptr damage = mk_checker()->check();
ASSERT_THAT(damage->size(), Gt(0u));
} }
//---------------------------------------------------------------- //----------------------------------------------------------------