From 20bf22e66278129b36a9fd5ebc597f5b2e011d37 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Thu, 17 Oct 2013 11:45:20 +0100 Subject: [PATCH] [caching] handle VARIABLE_HINT_SIZE incompat flag --- base/bits.h | 26 ++++++++++++++++++++++++++ caching/superblock.cc | 31 ++++++++++++++++++++++--------- caching/superblock.h | 4 ++++ unit-tests/cache_superblock_t.cc | 12 ++++++++++-- 4 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 base/bits.h diff --git a/base/bits.h b/base/bits.h new file mode 100644 index 0000000..bc71e2d --- /dev/null +++ b/base/bits.h @@ -0,0 +1,26 @@ +#ifndef BASE_BITS_H +#define BASE_BITS_H + +//---------------------------------------------------------------- + +namespace base { + template + bool test_bit(T flag, unsigned bit) { + return flag & (1 << bit); + } + + template + void set_bit(T &flag, unsigned bit) { + flag = flag | (1 << bit); + } + + template + void clear_bit(T &flag, unsigned bit) { + flag = flag & ~(1 << bit); + } +} + +//---------------------------------------------------------------- + +#endif + diff --git a/caching/superblock.cc b/caching/superblock.cc index 3eb7231..b4b6270 100644 --- a/caching/superblock.cc +++ b/caching/superblock.cc @@ -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(disk.compat_flags); + core.compat_ro_flags = to_cpu(disk.compat_ro_flags); + core.incompat_flags = to_cpu(disk.incompat_flags); + core.csum = to_cpu(disk.csum); core.flags = superblock_flags(to_cpu(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(disk.policy_version[i]); - core.policy_hint_size = core.version == 1 ? 4 : to_cpu(disk.policy_hint_size); + core.policy_hint_size = test_bit(core.incompat_flags, VARIABLE_HINT_SIZE_BIT) ? + to_cpu(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(disk.metadata_block_size); core.cache_blocks = to_cpu(disk.cache_blocks); - core.compat_flags = to_cpu(disk.compat_flags); - core.compat_ro_flags = to_cpu(disk.compat_ro_flags); - core.incompat_flags = to_cpu(disk.incompat_flags); - core.read_hits = to_cpu(disk.read_hits); core.read_misses = to_cpu(disk.read_misses); core.write_hits = to_cpu(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(core.csum); disk.flags = to_disk(core.flags.encode()); disk.blocknr = to_disk(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(core.policy_version[i]); - disk.policy_hint_size = to_disk(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(core.policy_hint_size); + } else { + clear_bit(core.incompat_flags, VARIABLE_HINT_SIZE_BIT); + disk.policy_hint_size = to_disk(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())); diff --git a/caching/superblock.h b/caching/superblock.h index 0b159c3..fb7af3c 100644 --- a/caching/superblock.h +++ b/caching/superblock.h @@ -77,6 +77,10 @@ namespace caching { uint32_t write_misses; }; + enum incompat_bits { + VARIABLE_HINT_SIZE_BIT = 0 + }; + //-------------------------------- namespace superblock_damage { diff --git a/unit-tests/cache_superblock_t.cc b/unit-tests/cache_superblock_t.cc index 0df64c4..03f1a8c 100644 --- a/unit-tests/cache_superblock_t.cc +++ b/unit-tests/cache_superblock_t.cc @@ -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(); }