Working on device_checker
This commit is contained in:
parent
524f9474cf
commit
969a5f62c6
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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),
|
||||||
|
@ -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 {
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user