[caching] handle VARIABLE_HINT_SIZE incompat flag

This commit is contained in:
Joe Thornber 2013-10-17 11:45:20 +01:00
parent c7b67659a5
commit 20bf22e662
4 changed files with 62 additions and 11 deletions

26
base/bits.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef BASE_BITS_H
#define BASE_BITS_H
//----------------------------------------------------------------
namespace base {
template <typename T>
bool test_bit(T flag, unsigned bit) {
return flag & (1 << bit);
}
template <typename T>
void set_bit(T &flag, unsigned bit) {
flag = flag | (1 << bit);
}
template <typename T>
void clear_bit(T &flag, unsigned bit) {
flag = flag & ~(1 << bit);
}
}
//----------------------------------------------------------------
#endif

View File

@ -1,5 +1,7 @@
#include "base/bits.h"
#include "caching/superblock.h"
using namespace base;
using namespace caching;
using namespace superblock_damage;
@ -111,7 +113,7 @@ superblock::superblock()
blocknr(SUPERBLOCK_LOCATION),
magic(SUPERBLOCK_MAGIC),
version(VERSION_END - 1u),
policy_hint_size(0),
policy_hint_size(4),
mapping_root(0),
hint_root(0),
discard_root(0),
@ -139,6 +141,10 @@ superblock::superblock()
void
superblock_traits::unpack(superblock_disk const &disk, superblock &core)
{
core.compat_flags = to_cpu<uint32_t>(disk.compat_flags);
core.compat_ro_flags = to_cpu<uint32_t>(disk.compat_ro_flags);
core.incompat_flags = to_cpu<uint32_t>(disk.incompat_flags);
core.csum = to_cpu<uint32_t>(disk.csum);
core.flags = superblock_flags(to_cpu<uint32_t>(disk.flags));
@ -153,7 +159,8 @@ superblock_traits::unpack(superblock_disk const &disk, superblock &core)
for (unsigned i = 0; i < CACHE_POLICY_VERSION_SIZE; i++)
core.policy_version[i] = to_cpu<uint32_t>(disk.policy_version[i]);
core.policy_hint_size = core.version == 1 ? 4 : to_cpu<uint32_t>(disk.policy_hint_size);
core.policy_hint_size = test_bit(core.incompat_flags, VARIABLE_HINT_SIZE_BIT) ?
to_cpu<uint32_t>(disk.policy_hint_size) : 4;
::memcpy(core.metadata_space_map_root,
disk.metadata_space_map_root,
@ -170,10 +177,6 @@ superblock_traits::unpack(superblock_disk const &disk, superblock &core)
core.metadata_block_size = to_cpu<uint32_t>(disk.metadata_block_size);
core.cache_blocks = to_cpu<uint32_t>(disk.cache_blocks);
core.compat_flags = to_cpu<uint32_t>(disk.compat_flags);
core.compat_ro_flags = to_cpu<uint32_t>(disk.compat_ro_flags);
core.incompat_flags = to_cpu<uint32_t>(disk.incompat_flags);
core.read_hits = to_cpu<uint32_t>(disk.read_hits);
core.read_misses = to_cpu<uint32_t>(disk.read_misses);
core.write_hits = to_cpu<uint32_t>(disk.write_hits);
@ -181,8 +184,11 @@ superblock_traits::unpack(superblock_disk const &disk, superblock &core)
}
void
superblock_traits::pack(superblock const &core, superblock_disk &disk)
superblock_traits::pack(superblock const &sb, superblock_disk &disk)
{
// We adjust some of the flags in the superblock, so make a copy
superblock core(sb);
disk.csum = to_disk<le32>(core.csum);
disk.flags = to_disk<le32>(core.flags.encode());
disk.blocknr = to_disk<le64>(core.blocknr);
@ -195,7 +201,14 @@ superblock_traits::pack(superblock const &core, superblock_disk &disk)
for (unsigned i = 0; i < CACHE_POLICY_VERSION_SIZE; i++)
disk.policy_version[i] = to_disk<le32>(core.policy_version[i]);
disk.policy_hint_size = to_disk<le32>(core.policy_hint_size);
if (core.policy_hint_size != 4) {
set_bit(core.incompat_flags, VARIABLE_HINT_SIZE_BIT);
disk.policy_hint_size = to_disk<le32>(core.policy_hint_size);
} else {
clear_bit(core.incompat_flags, VARIABLE_HINT_SIZE_BIT);
disk.policy_hint_size = to_disk<le32>(0u);
}
::memcpy(disk.metadata_space_map_root,
core.metadata_space_map_root,
@ -361,7 +374,7 @@ caching::check_superblock(superblock const &sb,
visitor.visit(superblock_invalid(msg.str()));
}
if (sb.incompat_flags != 0) {
if (sb.incompat_flags & ~(1 << VARIABLE_HINT_SIZE_BIT)) {
ostringstream msg;
msg << "incompat_flags invalid (can only be 0): " << sb.incompat_flags;
visitor.visit(superblock_invalid(msg.str()));

View File

@ -77,6 +77,10 @@ namespace caching {
uint32_t write_misses;
};
enum incompat_bits {
VARIABLE_HINT_SIZE_BIT = 0
};
//--------------------------------
namespace superblock_damage {

View File

@ -1,6 +1,8 @@
#include "gmock/gmock.h"
#include "base/bits.h"
#include "caching/superblock.h"
using namespace base;
using namespace caching;
using namespace superblock_damage;
using namespace testing;
@ -138,9 +140,15 @@ TEST_F(CacheSuperblockTests, compat_ro_flags_checked)
check_invalid();
}
TEST_F(CacheSuperblockTests, incompat_flags_checked)
TEST_F(CacheSuperblockTests, valid_incompat_flags_are_checked)
{
sb_.incompat_flags = 1;
set_bit(sb_.incompat_flags, VARIABLE_HINT_SIZE_BIT);
check();
}
TEST_F(CacheSuperblockTests, invalid_incompat_flags_checked)
{
set_bit(sb_.incompat_flags, 15);
check_invalid();
}