[cache_check] A whole bunch of superblock checks
This commit is contained in:
parent
7cd4728fbf
commit
42fd6b928b
@ -58,17 +58,27 @@ namespace {
|
||||
error_state err_;
|
||||
};
|
||||
|
||||
class superblock_reporter : public superblock_detail::damage_visitor, reporter_base {
|
||||
class superblock_reporter : public superblock_damage::damage_visitor, reporter_base {
|
||||
public:
|
||||
superblock_reporter(nested_output &o)
|
||||
: reporter_base(o) {
|
||||
}
|
||||
|
||||
virtual void visit(superblock_detail::superblock_corruption const &d) {
|
||||
virtual void visit(superblock_damage::superblock_corrupt const &d) {
|
||||
out() << "superblock is corrupt" << end_message();
|
||||
{
|
||||
nested_output::nest _ = push();
|
||||
out() << d.desc_ << end_message();
|
||||
out() << d.get_desc() << end_message();
|
||||
}
|
||||
|
||||
mplus_error(FATAL);
|
||||
}
|
||||
|
||||
virtual void visit(superblock_damage::superblock_invalid const &d) {
|
||||
out() << "superblock is invalid" << end_message();
|
||||
{
|
||||
nested_output::nest _ = push();
|
||||
out() << d.get_desc() << end_message();
|
||||
}
|
||||
|
||||
mplus_error(FATAL);
|
||||
@ -95,7 +105,7 @@ namespace {
|
||||
|
||||
transaction_manager::ptr open_tm(block_manager<>::ptr bm) {
|
||||
space_map::ptr sm(new core_map(bm->get_nr_blocks()));
|
||||
sm->inc(superblock_detail::SUPERBLOCK_LOCATION);
|
||||
sm->inc(SUPERBLOCK_LOCATION);
|
||||
transaction_manager::ptr tm(new transaction_manager(bm, sm));
|
||||
return tm;
|
||||
}
|
||||
@ -146,13 +156,13 @@ namespace {
|
||||
out << "examining superblock" << end_message();
|
||||
{
|
||||
nested_output::nest _ = out.push();
|
||||
check_superblock(bm, sb_rep);
|
||||
check_superblock(bm, bm->get_nr_blocks(), sb_rep);
|
||||
}
|
||||
|
||||
if (sb_rep.get_error() == FATAL)
|
||||
return FATAL;
|
||||
|
||||
superblock_detail::superblock sb = read_superblock(bm);
|
||||
superblock sb = read_superblock(bm);
|
||||
transaction_manager::ptr tm = open_tm(bm);
|
||||
|
||||
if (fs.check_mappings_) {
|
||||
|
@ -7,8 +7,6 @@ using namespace caching;
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
using namespace superblock_detail;
|
||||
|
||||
unsigned const METADATA_CACHE_SIZE = 1024;
|
||||
|
||||
// FIXME: duplication
|
||||
@ -133,9 +131,7 @@ metadata::commit_hints()
|
||||
void
|
||||
metadata::commit_superblock()
|
||||
{
|
||||
write_ref superblock = tm_->get_bm()->superblock_zero(SUPERBLOCK_LOCATION, superblock_validator());
|
||||
superblock_disk *disk = reinterpret_cast<superblock_disk *>(superblock.data().raw());
|
||||
superblock_traits::pack(sb_, *disk);
|
||||
write_superblock(tm_->get_bm(), sb_);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
@ -33,7 +33,7 @@ namespace caching {
|
||||
|
||||
typedef persistent_data::transaction_manager tm;
|
||||
tm::ptr tm_;
|
||||
superblock_detail::superblock sb_;
|
||||
superblock sb_;
|
||||
checked_space_map::ptr metadata_sm_;
|
||||
mapping_array::ptr mappings_;
|
||||
hint_array::ptr hints_;
|
||||
|
@ -5,7 +5,7 @@
|
||||
using namespace caching;
|
||||
using namespace mapping_array_detail;
|
||||
using namespace std;
|
||||
using namespace superblock_detail;
|
||||
using namespace superblock_damage;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
@ -27,38 +27,14 @@ namespace {
|
||||
size_t hint_width) {
|
||||
|
||||
superblock &sb = md_->sb_;
|
||||
|
||||
sb.flags = 0;
|
||||
memset(sb.uuid, 0, sizeof(sb.uuid));
|
||||
sb.magic = caching::superblock_detail::SUPERBLOCK_MAGIC;
|
||||
sb.version = 0; // FIXME: fix
|
||||
strncpy((char *) sb.policy_name, policy.c_str(), sizeof(sb.policy_name));
|
||||
memset(sb.policy_version, 0, sizeof(sb.policy_version));
|
||||
memset(sb.policy_version, 0, sizeof(sb.policy_version)); // FIXME: should come from xml
|
||||
sb.policy_hint_size = hint_width;
|
||||
md_->setup_hint_array(hint_width);
|
||||
|
||||
memset(sb.metadata_space_map_root, 0,
|
||||
sizeof(sb.metadata_space_map_root));
|
||||
sb.mapping_root = 0;
|
||||
sb.hint_root = 0;
|
||||
|
||||
sb.discard_root = 0;
|
||||
sb.discard_block_size = 0;
|
||||
sb.discard_nr_blocks = 0;
|
||||
|
||||
sb.data_block_size = block_size;
|
||||
sb.metadata_block_size = 0;
|
||||
sb.cache_blocks = nr_cache_blocks;
|
||||
|
||||
sb.compat_flags = 0;
|
||||
sb.compat_ro_flags = 0;
|
||||
sb.incompat_flags = 0;
|
||||
|
||||
sb.read_hits = 0;
|
||||
sb.read_misses = 0;
|
||||
sb.write_hits = 0;
|
||||
sb.write_misses = 0;
|
||||
|
||||
struct mapping unmapped_value;
|
||||
unmapped_value.oblock_ = 0;
|
||||
unmapped_value.flags_ = 0;
|
||||
|
@ -1,7 +1,92 @@
|
||||
#include "caching/superblock.h"
|
||||
|
||||
using namespace caching;
|
||||
using namespace superblock_detail;
|
||||
using namespace superblock_damage;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
using namespace base;
|
||||
|
||||
struct superblock_disk {
|
||||
le32 csum;
|
||||
le32 flags;
|
||||
le64 blocknr;
|
||||
|
||||
__u8 uuid[16];
|
||||
le64 magic;
|
||||
le32 version;
|
||||
|
||||
__u8 policy_name[CACHE_POLICY_NAME_SIZE];
|
||||
le32 policy_version[CACHE_POLICY_VERSION_SIZE];
|
||||
le32 policy_hint_size;
|
||||
|
||||
__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
|
||||
|
||||
le64 mapping_root;
|
||||
le64 hint_root;
|
||||
|
||||
le64 discard_root;
|
||||
le64 discard_block_size;
|
||||
le64 discard_nr_blocks;
|
||||
|
||||
le32 data_block_size; /* in 512-byte sectors */
|
||||
le32 metadata_block_size; /* in 512-byte sectors */
|
||||
le32 cache_blocks;
|
||||
|
||||
le32 compat_flags;
|
||||
le32 compat_ro_flags;
|
||||
le32 incompat_flags;
|
||||
|
||||
le32 read_hits;
|
||||
le32 read_misses;
|
||||
le32 write_hits;
|
||||
le32 write_misses;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct superblock_traits {
|
||||
typedef superblock_disk disk_type;
|
||||
typedef superblock value_type;
|
||||
|
||||
static void unpack(superblock_disk const &disk, superblock &value);
|
||||
static void pack(superblock const &value, superblock_disk &disk);
|
||||
};
|
||||
|
||||
uint32_t const SUPERBLOCK_MAGIC = 06142003;
|
||||
uint32_t const VERSION_BEGIN = 1;
|
||||
uint32_t const VERSION_END = 2;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
superblock::superblock()
|
||||
: csum(0),
|
||||
flags(0),
|
||||
blocknr(SUPERBLOCK_LOCATION),
|
||||
magic(SUPERBLOCK_MAGIC),
|
||||
version(VERSION_BEGIN),
|
||||
policy_hint_size(0),
|
||||
mapping_root(0),
|
||||
hint_root(0),
|
||||
discard_root(0),
|
||||
discard_block_size(0),
|
||||
discard_nr_blocks(0),
|
||||
data_block_size(0),
|
||||
metadata_block_size(8),
|
||||
cache_blocks(0),
|
||||
compat_flags(0),
|
||||
compat_ro_flags(0),
|
||||
incompat_flags(0),
|
||||
read_hits(0),
|
||||
read_misses(0),
|
||||
write_hits(0),
|
||||
write_misses(0)
|
||||
{
|
||||
::memset(uuid, 0, sizeof(uuid));
|
||||
::memset(policy_name, 0, sizeof(policy_name));
|
||||
::memset(policy_version, 0, sizeof(policy_version));
|
||||
::memset(metadata_space_map_root, 0, sizeof(metadata_space_map_root));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
@ -94,22 +179,33 @@ superblock_traits::pack(superblock const &core, superblock_disk &disk)
|
||||
|
||||
//--------------------------------
|
||||
|
||||
superblock_corruption::superblock_corruption(std::string const &desc)
|
||||
: desc_(desc)
|
||||
superblock_corrupt::superblock_corrupt(std::string const &desc)
|
||||
: damage(desc)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
superblock_corruption::visit(damage_visitor &v) const
|
||||
superblock_corrupt::visit(damage_visitor &v) const
|
||||
{
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
superblock_invalid::superblock_invalid(std::string const &desc)
|
||||
: damage(desc)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
superblock_invalid::visit(damage_visitor &v) const
|
||||
{
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
|
||||
namespace {
|
||||
// anonymous namespace doesn't work for some reason
|
||||
namespace validator {
|
||||
using namespace persistent_data;
|
||||
using namespace superblock_detail;
|
||||
|
||||
uint32_t const VERSION = 1;
|
||||
unsigned const SECTOR_TO_BLOCK_SHIFT = 3;
|
||||
@ -131,65 +227,122 @@ namespace {
|
||||
sbd->csum = to_disk<base::le32>(sum.get_sum());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
persistent_data::block_manager<>::validator::ptr
|
||||
caching::superblock_validator()
|
||||
{
|
||||
return block_manager<>::validator::ptr(new sb_validator);
|
||||
block_manager<>::validator::ptr mk_v() {
|
||||
return block_manager<>::validator::ptr(new sb_validator);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
|
||||
superblock_detail::superblock
|
||||
superblock
|
||||
caching::read_superblock(block_manager<>::ptr bm, block_address location)
|
||||
{
|
||||
using namespace superblock_detail;
|
||||
|
||||
superblock sb;
|
||||
block_manager<>::read_ref r = bm->read_lock(location, superblock_validator());
|
||||
block_manager<>::read_ref r = bm->read_lock(location, validator::mk_v());
|
||||
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(&r.data());
|
||||
superblock_traits::unpack(*sbd, sb);
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
superblock_detail::superblock
|
||||
caching::read_superblock(persistent_data::block_manager<>::ptr bm)
|
||||
void
|
||||
caching::write_superblock(block_manager<>::ptr bm, superblock const &sb, block_address location)
|
||||
{
|
||||
return read_superblock(bm, SUPERBLOCK_LOCATION);
|
||||
block_manager<>::write_ref w = bm->superblock_zero(location, validator::mk_v());
|
||||
superblock_traits::pack(sb, *reinterpret_cast<superblock_disk *>(w.data().raw()));
|
||||
}
|
||||
|
||||
void
|
||||
caching::write_superblock(block_manager<>::ptr bm,
|
||||
block_address location,
|
||||
superblock_detail::superblock const &sb)
|
||||
caching::check_superblock(superblock const &sb,
|
||||
block_address nr_metadata_blocks,
|
||||
damage_visitor &visitor)
|
||||
{
|
||||
using namespace superblock_detail;
|
||||
if (sb.flags != 0) {
|
||||
ostringstream msg;
|
||||
msg << "invalid flags: " << hex << sb.flags;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
block_manager<>::write_ref w = bm->write_lock(location, superblock_validator());
|
||||
superblock_traits::pack(sb, *reinterpret_cast<superblock_disk *>(&w.data()));
|
||||
}
|
||||
if (sb.blocknr >= nr_metadata_blocks) {
|
||||
ostringstream msg;
|
||||
msg << "blocknr out of bounds: " << sb.blocknr << " >= " << nr_metadata_blocks;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
void
|
||||
caching::write_superblock(block_manager<>::ptr bm,
|
||||
superblock_detail::superblock const &sb)
|
||||
{
|
||||
write_superblock(bm, SUPERBLOCK_LOCATION, sb);
|
||||
if (sb.magic != SUPERBLOCK_MAGIC) {
|
||||
ostringstream msg;
|
||||
msg << "magic in incorrect: " << sb.magic;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
if (sb.version >= VERSION_END) {
|
||||
ostringstream msg;
|
||||
msg << "version incorrect: " << sb.version;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
if (sb.version < VERSION_BEGIN) {
|
||||
ostringstream msg;
|
||||
msg << "version incorrect: " << sb.version;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
if (::strnlen((char const *) sb.policy_name, CACHE_POLICY_NAME_SIZE) == CACHE_POLICY_NAME_SIZE) {
|
||||
visitor.visit(superblock_invalid("policy name is not null terminated"));
|
||||
}
|
||||
|
||||
if (sb.policy_hint_size % 4 || sb.policy_hint_size > 128) {
|
||||
ostringstream msg;
|
||||
msg << "policy hint size invalid: " << sb.policy_hint_size;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
if (sb.metadata_block_size != 8) {
|
||||
ostringstream msg;
|
||||
msg << "metadata block size incorrect: " << sb.metadata_block_size;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
if (sb.compat_flags != 0) {
|
||||
ostringstream msg;
|
||||
msg << "compat_flags invalid (can only be 0): " << sb.compat_flags;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
if (sb.compat_ro_flags != 0) {
|
||||
ostringstream msg;
|
||||
msg << "compat_ro_flags invalid (can only be 0): " << sb.compat_ro_flags;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
|
||||
if (sb.incompat_flags != 0) {
|
||||
ostringstream msg;
|
||||
msg << "incompat_flags invalid (can only be 0): " << sb.incompat_flags;
|
||||
visitor.visit(superblock_invalid(msg.str()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
caching::check_superblock(persistent_data::block_manager<>::ptr bm,
|
||||
superblock_detail::damage_visitor &visitor)
|
||||
block_address nr_metadata_blocks,
|
||||
damage_visitor &visitor)
|
||||
{
|
||||
using namespace superblock_detail;
|
||||
superblock sb;
|
||||
|
||||
try {
|
||||
bm->read_lock(SUPERBLOCK_LOCATION, superblock_validator());
|
||||
sb = read_superblock(bm, SUPERBLOCK_LOCATION);
|
||||
|
||||
} catch (std::exception const &e) {
|
||||
visitor.visit(superblock_corruption(e.what()));
|
||||
|
||||
// FIXME: what if it fails due to a zero length file? Not
|
||||
// really a corruption, so much as an io error. Should we
|
||||
// separate these?
|
||||
|
||||
visitor.visit(superblock_corrupt(e.what()));
|
||||
}
|
||||
|
||||
check_superblock(sb, nr_metadata_blocks, visitor);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
@ -7,112 +7,82 @@
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace caching {
|
||||
namespace superblock_detail {
|
||||
using namespace base;
|
||||
typedef unsigned char __u8;
|
||||
|
||||
unsigned const SPACE_MAP_ROOT_SIZE = 128;
|
||||
unsigned const CACHE_POLICY_NAME_SIZE = 16;
|
||||
unsigned const CACHE_POLICY_VERSION_SIZE = 3;
|
||||
unsigned const SPACE_MAP_ROOT_SIZE = 128;
|
||||
unsigned const CACHE_POLICY_NAME_SIZE = 16;
|
||||
unsigned const CACHE_POLICY_VERSION_SIZE = 3;
|
||||
block_address const SUPERBLOCK_LOCATION = 0;
|
||||
|
||||
typedef unsigned char __u8;
|
||||
struct superblock {
|
||||
superblock();
|
||||
|
||||
struct superblock_disk {
|
||||
le32 csum;
|
||||
le32 flags;
|
||||
le64 blocknr;
|
||||
uint32_t csum;
|
||||
uint32_t flags;
|
||||
uint64_t blocknr;
|
||||
|
||||
__u8 uuid[16];
|
||||
le64 magic;
|
||||
le32 version;
|
||||
__u8 uuid[16];
|
||||
uint64_t magic;
|
||||
uint32_t version;
|
||||
|
||||
__u8 policy_name[CACHE_POLICY_NAME_SIZE];
|
||||
le32 policy_version[CACHE_POLICY_VERSION_SIZE];
|
||||
le32 policy_hint_size;
|
||||
__u8 policy_name[CACHE_POLICY_NAME_SIZE];
|
||||
uint32_t policy_version[CACHE_POLICY_VERSION_SIZE];
|
||||
uint32_t policy_hint_size;
|
||||
|
||||
__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
|
||||
__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
|
||||
|
||||
le64 mapping_root;
|
||||
le64 hint_root;
|
||||
uint64_t mapping_root;
|
||||
uint64_t hint_root;
|
||||
|
||||
le64 discard_root;
|
||||
le64 discard_block_size;
|
||||
le64 discard_nr_blocks;
|
||||
uint64_t discard_root;
|
||||
uint64_t discard_block_size;
|
||||
uint64_t discard_nr_blocks;
|
||||
|
||||
le32 data_block_size; /* in 512-byte sectors */
|
||||
le32 metadata_block_size; /* in 512-byte sectors */
|
||||
le32 cache_blocks;
|
||||
uint32_t data_block_size; /* in 512-byte sectors */
|
||||
uint32_t metadata_block_size; /* in 512-byte sectors */
|
||||
uint32_t cache_blocks;
|
||||
|
||||
le32 compat_flags;
|
||||
le32 compat_ro_flags;
|
||||
le32 incompat_flags;
|
||||
uint32_t compat_flags;
|
||||
uint32_t compat_ro_flags;
|
||||
uint32_t incompat_flags;
|
||||
|
||||
le32 read_hits;
|
||||
le32 read_misses;
|
||||
le32 write_hits;
|
||||
le32 write_misses;
|
||||
} __attribute__ ((packed));
|
||||
uint32_t read_hits;
|
||||
uint32_t read_misses;
|
||||
uint32_t write_hits;
|
||||
uint32_t write_misses;
|
||||
};
|
||||
|
||||
struct superblock {
|
||||
uint32_t csum;
|
||||
uint32_t flags;
|
||||
uint64_t blocknr;
|
||||
//--------------------------------
|
||||
|
||||
__u8 uuid[16];
|
||||
uint64_t magic;
|
||||
uint32_t version;
|
||||
|
||||
__u8 policy_name[CACHE_POLICY_NAME_SIZE];
|
||||
uint32_t policy_version[CACHE_POLICY_VERSION_SIZE];
|
||||
uint32_t policy_hint_size;
|
||||
|
||||
__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
|
||||
|
||||
uint64_t mapping_root;
|
||||
uint64_t hint_root;
|
||||
|
||||
uint64_t discard_root;
|
||||
uint64_t discard_block_size;
|
||||
uint64_t discard_nr_blocks;
|
||||
|
||||
uint32_t data_block_size; /* in 512-byte sectors */
|
||||
uint32_t metadata_block_size; /* in 512-byte sectors */
|
||||
uint32_t cache_blocks;
|
||||
|
||||
uint32_t compat_flags;
|
||||
uint32_t compat_ro_flags;
|
||||
uint32_t incompat_flags;
|
||||
|
||||
uint32_t read_hits;
|
||||
uint32_t read_misses;
|
||||
uint32_t write_hits;
|
||||
uint32_t write_misses;
|
||||
};
|
||||
|
||||
struct superblock_traits {
|
||||
typedef superblock_disk disk_type;
|
||||
typedef superblock value_type;
|
||||
|
||||
static void unpack(superblock_disk const &disk, superblock &value);
|
||||
static void pack(superblock const &value, superblock_disk &disk);
|
||||
};
|
||||
|
||||
block_address const SUPERBLOCK_LOCATION = 0;
|
||||
uint32_t const SUPERBLOCK_MAGIC = 06142003;
|
||||
|
||||
//--------------------------------
|
||||
namespace superblock_damage {
|
||||
|
||||
class damage_visitor;
|
||||
|
||||
struct damage {
|
||||
class damage {
|
||||
public:
|
||||
damage(std::string const &desc)
|
||||
: desc_(desc) {
|
||||
}
|
||||
|
||||
virtual ~damage() {}
|
||||
virtual void visit(damage_visitor &v) const = 0;
|
||||
|
||||
std::string const &get_desc() const {
|
||||
return desc_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string desc_;
|
||||
};
|
||||
|
||||
struct superblock_corruption : public damage {
|
||||
superblock_corruption(std::string const &desc);
|
||||
struct superblock_corrupt : public damage {
|
||||
superblock_corrupt(std::string const &desc);
|
||||
void visit(damage_visitor &v) const;
|
||||
};
|
||||
|
||||
std::string desc_;
|
||||
struct superblock_invalid : public damage {
|
||||
superblock_invalid(std::string const &desc);
|
||||
void visit(damage_visitor &v) const;
|
||||
};
|
||||
|
||||
class damage_visitor {
|
||||
@ -121,24 +91,29 @@ namespace caching {
|
||||
|
||||
void visit(damage const &d);
|
||||
|
||||
virtual void visit(superblock_corruption const &d) = 0;
|
||||
virtual void visit(superblock_corrupt const &d) = 0;
|
||||
virtual void visit(superblock_invalid const &d) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
|
||||
persistent_data::block_manager<>::validator::ptr superblock_validator();
|
||||
|
||||
superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm);
|
||||
superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm,
|
||||
persistent_data::block_address location);
|
||||
superblock read_superblock(persistent_data::block_manager<>::ptr bm,
|
||||
persistent_data::block_address location = SUPERBLOCK_LOCATION);
|
||||
|
||||
void write_superblock(persistent_data::block_manager<>::ptr bm,
|
||||
superblock_detail::superblock const &sb);
|
||||
void write_superblock(persistent_data::block_manager<>::ptr bm,
|
||||
persistent_data::block_address location,
|
||||
superblock_detail::superblock const &sb);
|
||||
superblock const &sb,
|
||||
persistent_data::block_address location = SUPERBLOCK_LOCATION);
|
||||
|
||||
void check_superblock(superblock const &sb,
|
||||
persistent_data::block_address nr_metadata_blocks,
|
||||
superblock_damage::damage_visitor &visitor);
|
||||
|
||||
void check_superblock(persistent_data::block_manager<>::ptr bm,
|
||||
superblock_detail::damage_visitor &visitor);
|
||||
persistent_data::block_address nr_metadata_blocks,
|
||||
superblock_damage::damage_visitor &visitor);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
@ -53,6 +53,7 @@ TEST_SOURCE=\
|
||||
unit-tests/btree_damage_visitor_t.cc \
|
||||
unit-tests/buffer_t.cc \
|
||||
unit-tests/cache_t.cc \
|
||||
unit-tests/cache_superblock_t.cc \
|
||||
unit-tests/damage_tracker_t.cc \
|
||||
unit-tests/endian_t.cc \
|
||||
unit-tests/rmap_visitor_t.cc \
|
||||
|
140
unit-tests/cache_superblock_t.cc
Normal file
140
unit-tests/cache_superblock_t.cc
Normal file
@ -0,0 +1,140 @@
|
||||
#include "gmock/gmock.h"
|
||||
#include "caching/superblock.h"
|
||||
|
||||
using namespace caching;
|
||||
using namespace superblock_damage;
|
||||
using namespace testing;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
class damage_visitor_mock : public damage_visitor {
|
||||
public:
|
||||
MOCK_METHOD1(visit, void(superblock_corrupt const &));
|
||||
MOCK_METHOD1(visit, void(superblock_invalid const &));
|
||||
};
|
||||
|
||||
class CacheSuperblockTests : public Test {
|
||||
public:
|
||||
CacheSuperblockTests() {
|
||||
}
|
||||
|
||||
void check() {
|
||||
check_superblock(sb_, 100, visitor_);
|
||||
}
|
||||
|
||||
void expect_invalid() {
|
||||
EXPECT_CALL(visitor_, visit(Matcher<superblock_invalid const &>(_))).Times(1);
|
||||
}
|
||||
|
||||
void check_invalid() {
|
||||
expect_invalid();
|
||||
check();
|
||||
}
|
||||
|
||||
damage_visitor_mock visitor_;
|
||||
superblock sb_;
|
||||
};
|
||||
|
||||
bool operator ==(superblock_corrupt const &lhs, superblock_corrupt const &rhs) {
|
||||
return lhs.get_desc() == rhs.get_desc();
|
||||
}
|
||||
|
||||
bool operator ==(superblock_invalid const &lhs, superblock_invalid const &rhs) {
|
||||
return lhs.get_desc() == rhs.get_desc();
|
||||
}
|
||||
|
||||
ostream &operator <<(ostream &out, damage const &d) {
|
||||
out << d.get_desc();
|
||||
return out;
|
||||
}
|
||||
|
||||
ostream &operator <<(ostream &out, superblock_invalid const &d) {
|
||||
out << "superblock_invalid: " << d.get_desc();
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
TEST_F(CacheSuperblockTests, default_constructed_superblock_is_valid)
|
||||
{
|
||||
sb_.flags = 0;
|
||||
check();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, non_zero_flags_are_invalid)
|
||||
{
|
||||
sb_.flags = 1;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, blocknr_is_in_range)
|
||||
{
|
||||
sb_.blocknr = 101;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, magic_is_checked)
|
||||
{
|
||||
sb_.magic = 12345;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, version_gt_1_is_checked)
|
||||
{
|
||||
sb_.version = 2;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, version_lt_1_is_checked)
|
||||
{
|
||||
sb_.version = 0;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, policy_name_must_be_null_terminated)
|
||||
{
|
||||
for (unsigned i = 0; i < CACHE_POLICY_NAME_SIZE; i++)
|
||||
sb_.policy_name[i] = 'a';
|
||||
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, policy_hint_size_checked)
|
||||
{
|
||||
sb_.policy_hint_size = 3;
|
||||
check_invalid();
|
||||
|
||||
sb_.policy_hint_size = 129;
|
||||
check_invalid();
|
||||
|
||||
sb_.policy_hint_size = 132;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, metadata_block_size_checked)
|
||||
{
|
||||
sb_.metadata_block_size = 16;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, compat_flags_checked)
|
||||
{
|
||||
sb_.compat_flags = 1;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, compat_ro_flags_checked)
|
||||
{
|
||||
sb_.compat_ro_flags = 1;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
TEST_F(CacheSuperblockTests, incompat_flags_checked)
|
||||
{
|
||||
sb_.incompat_flags = 1;
|
||||
check_invalid();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
Loading…
Reference in New Issue
Block a user