diff --git a/caching/superblock.cc b/caching/superblock.cc index f4d09db..f560fdf 100644 --- a/caching/superblock.cc +++ b/caching/superblock.cc @@ -59,9 +59,53 @@ namespace { //---------------------------------------------------------------- +superblock_flags::superblock_flags() +{ +} + +superblock_flags::superblock_flags(uint32_t bits) +{ + if (bits & (1 << CLEAN_SHUTDOWN_BIT)) { + flags_.insert(CLEAN_SHUTDOWN); + bits &= ~(1 << CLEAN_SHUTDOWN_BIT); + } + + unhandled_flags_ = bits; +} + +void +superblock_flags::set_flag(superblock_flags::flag f) +{ + flags_.insert(f); +} + +bool +superblock_flags::get_flag(flag f) const +{ + return flags_.find(f) != flags_.end(); +} + +uint32_t +superblock_flags::encode() const +{ + uint32_t r = 0; + + if (get_flag(CLEAN_SHUTDOWN)) + r = r | (1 << CLEAN_SHUTDOWN_BIT); + + return r; +} + +uint32_t +superblock_flags::get_unhandled_flags() const +{ + return unhandled_flags_; +} + +//---------------------------------------------------------------- + superblock::superblock() : csum(0), - flags(0), blocknr(SUPERBLOCK_LOCATION), magic(SUPERBLOCK_MAGIC), version(VERSION_BEGIN), @@ -94,7 +138,8 @@ void superblock_traits::unpack(superblock_disk const &disk, superblock &core) { core.csum = to_cpu(disk.csum); - core.flags = to_cpu(disk.flags); + + core.flags = superblock_flags(to_cpu(disk.flags)); core.blocknr = to_cpu(disk.blocknr); ::memcpy(core.uuid, disk.uuid, sizeof(core.uuid)); @@ -137,7 +182,7 @@ void superblock_traits::pack(superblock const &core, superblock_disk &disk) { disk.csum = to_disk(core.csum); - disk.flags = to_disk(core.flags); + disk.flags = to_disk(core.flags.encode()); disk.blocknr = to_disk(core.blocknr); ::memcpy(disk.uuid, core.uuid, sizeof(disk.uuid)); @@ -257,9 +302,9 @@ caching::check_superblock(superblock const &sb, block_address nr_metadata_blocks, damage_visitor &visitor) { - if (sb.flags != 0) { + if (sb.flags.get_unhandled_flags()) { ostringstream msg; - msg << "invalid flags: " << hex << sb.flags; + msg << "invalid flags: " << sb.flags.get_unhandled_flags(); visitor.visit(superblock_invalid(msg.str())); } diff --git a/caching/superblock.h b/caching/superblock.h index 390970d..0b159c3 100644 --- a/caching/superblock.h +++ b/caching/superblock.h @@ -4,6 +4,8 @@ #include "persistent-data/endian_utils.h" #include "persistent-data/data-structures/btree.h" +#include + //---------------------------------------------------------------- namespace caching { @@ -14,11 +16,34 @@ namespace caching { unsigned const CACHE_POLICY_VERSION_SIZE = 3; block_address const SUPERBLOCK_LOCATION = 0; + class superblock_flags { + public: + enum flag { + CLEAN_SHUTDOWN + }; + + enum flag_bits { + CLEAN_SHUTDOWN_BIT = 0 + }; + + superblock_flags(); + superblock_flags(uint32_t bits); + + void set_flag(flag f); + bool get_flag(flag f) const; + uint32_t encode() const; + uint32_t get_unhandled_flags() const; + + private: + uint32_t unhandled_flags_; + std::set flags_; + }; + struct superblock { superblock(); uint32_t csum; - uint32_t flags; + superblock_flags flags; uint64_t blocknr; __u8 uuid[16];