#ifndef THIN_SUPERBLOCK_H #define THIN_SUPERBLOCK_H #include "base/endian_utils.h" #include "persistent-data/block.h" #include "persistent-data/data-structures/ref_counter.h" //---------------------------------------------------------------- namespace thin_provisioning { namespace superblock_detail { using namespace base; using namespace persistent_data; unsigned const SPACE_MAP_ROOT_SIZE = 128; typedef unsigned char __u8; struct superblock_disk { le32 csum_; le32 flags_; le64 blocknr_; __u8 uuid_[16]; le64 magic_; le32 version_; le32 time_; le64 trans_id_; /* root for userspace's transaction (for migration and friends) */ le64 metadata_snap_; __u8 data_space_map_root_[SPACE_MAP_ROOT_SIZE]; __u8 metadata_space_map_root_[SPACE_MAP_ROOT_SIZE]; /* 2 level btree mapping (dev_id, (dev block, time)) -> data block */ le64 data_mapping_root_; /* device detail root mapping dev_id -> device_details */ le64 device_details_root_; le32 data_block_size_; /* in 512-byte sectors */ le32 metadata_block_size_; /* in 512-byte sectors */ le64 metadata_nr_blocks_; le32 compat_flags_; le32 compat_ro_flags_; le32 incompat_flags_; } __attribute__ ((packed)); struct superblock { uint32_t csum_; uint32_t flags_; uint64_t blocknr_; unsigned char uuid_[16]; uint64_t magic_; uint32_t version_; uint32_t time_; uint64_t trans_id_; /* root for userspace's transaction (for migration and friends) */ uint64_t metadata_snap_; unsigned char data_space_map_root_[SPACE_MAP_ROOT_SIZE]; unsigned char metadata_space_map_root_[SPACE_MAP_ROOT_SIZE]; /* 2 level btree mapping (dev_id, (dev block, time)) -> data block */ uint64_t data_mapping_root_; /* device detail root mapping dev_id -> device_details */ uint64_t device_details_root_; uint32_t data_block_size_; /* in 512-byte sectors */ uint32_t metadata_block_size_; /* in 512-byte sectors */ uint64_t metadata_nr_blocks_; uint32_t compat_flags_; uint32_t compat_ro_flags_; uint32_t incompat_flags_; bool get_needs_check_flag() const; void set_needs_check_flag(bool val = true); }; struct superblock_traits { typedef superblock_disk disk_type; typedef superblock value_type; typedef no_op_ref_counter ref_counter; static void unpack(superblock_disk const &disk, superblock &core); static void pack(superblock const &core, superblock_disk &disk); }; block_address const SUPERBLOCK_LOCATION = 0; uint32_t const SUPERBLOCK_MAGIC = 27022010; uint32_t const METADATA_VERSION = 2; //-------------------------------- class damage_visitor; struct damage { virtual ~damage() {} virtual void visit(damage_visitor &v) const = 0; }; struct superblock_corruption : public damage { superblock_corruption(std::string const &desc); void visit(damage_visitor &v) const; std::string desc_; }; class damage_visitor { public: virtual ~damage_visitor() {} void visit(damage const &d); virtual void visit(superblock_corruption const &d) = 0; }; } bcache::validator::ptr superblock_validator(); // FIXME: should we put init_superblock in here too? // FIXME: make the bm const, and pass by reference rather than ptr superblock_detail::superblock read_superblock(persistent_data::block_manager const &bm); 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); void write_superblock(persistent_data::block_manager::ptr bm, superblock_detail::superblock const &sb); void check_superblock(persistent_data::block_manager::ptr bm, superblock_detail::damage_visitor &visitor, persistent_data::block_address sb_location = superblock_detail::SUPERBLOCK_LOCATION); } //---------------------------------------------------------------- #endif