diff --git a/era/bloom_tree.h b/era/bloom_tree.h new file mode 100644 index 0000000..e98ed37 --- /dev/null +++ b/era/bloom_tree.h @@ -0,0 +1,112 @@ +#ifndef ERA_BLOOM_TREE_H +#define ERA_BLOOM_TREE_H + +//---------------------------------------------------------------- + +namespace era { +} + +//---------------------------------------------------------------- + +#endif + + +#if 0 + class dm_era { + public: + dm_era(block_address nr_blocks) + : nr_blocks_(nr_blocks), + era_base_(0), + base_(nr_blocks, false) { + } + + set blocks_written_since(unsigned era) const { + + } + + unsigned get_era() const { + return era_base_ + eras_.size() - 1; + } + + void record_write(block_address b) { + current_era.record_write(b); + } + + void resize(block_address new_size) { + nr_blocks_ = new_size; + push_era(); + base_.resize(new_size, false); + } + + private: + era_details ¤t_era() { + return eras_.back(); + } + + void need_new_era() { + // ??? + } + + void push_era() { + eras_.push_back(era(nr_blocks_)); + if (eras_.size() > 100) + pop_era(); + } + + void pop_era() { + era_base_++; + + + + eras_.pop_front(); + } + + static const unsigned NR_PROBES = 6; + + class era_details { + public: + era_details(block_address nr_blocks) + : nr_blocks_(nr_blocks), + f(power_bits(nr_blocks, NR_PROBES)) { + } + + void record_write(block_address b) { + f.add(b); + } + + void add_blocks_written(set filter; + + block_address nr_blocks; + filter f; + }; + + space_map::ptr setup_core_map() { + space_map::ptr sm(new core_map(NR_BLOCKS)); + sm->inc(SUPERBLOCK); + return sm; + } + + block_address nr_blocks_; + unsigned era_base_; + vector base_; + deque eras_; + }; +#endif diff --git a/era/superblock.cc b/era/superblock.cc new file mode 100644 index 0000000..ed3ebb8 --- /dev/null +++ b/era/superblock.cc @@ -0,0 +1,118 @@ +#include "era/superblock.h" + +#include "persistent-data/checksum.h" + +using namespace base; +using namespace era; +using namespace persistent_data; + +//---------------------------------------------------------------- + +namespace { + using namespace base; + + struct superblock_disk { + le32 csum; + le32 flags; + le64 blocknr; + + __u8 uuid[16]; + le64 magic; + le32 version; + + le32 data_block_size; + le32 metadata_block_size; + le32 nr_blocks; + + le32 current_era; + era_detail_disk current_detail; + + le64 bloom_filters_root; + le64 era_array_root; + } __attribute__ ((packed)); + + struct superblock_traits { + typedef superblock_disk disk_type; + typedef superblock value_type; + + static void unpack(disk_type const &disk, value_type &value); + static void pack(value_type const &value, disk_type &disk); + }; + + uint32_t const SUPERBLOCK_MAGIC = 2126579579; + uint32_t const VERSION_BEGIN = 1; + uint32_t const VERSION_END = 2; +} + +//---------------------------------------------------------------- + +superblock::superblock() + : csum(0), + blocknr(0), + flags(), + magic(SUPERBLOCK_MAGIC), + version(VERSION_END - 1), + data_block_size(0), + metadata_block_size(8), + nr_blocks(0), + current_era(0), + era_root(0), + era_array_root(0) +{ + memset(uuid, 0, sizeof(uuid)); + memset(metadata_space_map_root, 0, sizeof(metadata_space_map_root)); +} + +//---------------------------------------------------------------- + +namespace validator { + using namespace persistent_data; + + uint32_t const VERSION = 1; + unsigned const SECTOR_TO_BLOCK_SHIFT = 3; + uint32_t const SUPERBLOCK_CSUM_SEED = 146538381; + + // FIXME: turn into a template, we have 3 similar classes now + struct sb_validator : public block_manager<>::validator { + virtual void check(buffer<> const &b, block_address location) const { + superblock_disk const *sbd = reinterpret_cast(&b); + crc32c sum(SUPERBLOCK_CSUM_SEED); + sum.append(&sbd->flags, MD_BLOCK_SIZE - sizeof(uint32_t)); + if (sum.get_sum() != to_cpu(sbd->csum)) + throw checksum_error("bad checksum in superblock"); + } + + virtual void prepare(buffer<> &b, block_address location) const { + superblock_disk *sbd = reinterpret_cast(&b); + crc32c sum(SUPERBLOCK_CSUM_SEED); + sum.append(&sbd->flags, MD_BLOCK_SIZE - sizeof(uint32_t)); + sbd->csum = to_disk(sum.get_sum()); + } + }; + + block_manager<>::validator::ptr mk_v() { + return block_manager<>::validator::ptr(new sb_validator); + } +} + +//---------------------------------------------------------------- + +superblock +era::read_superblock(block_manager<>::ptr bm, block_address location) +{ + superblock sb; + block_manager<>::read_ref r = bm->read_lock(location, validator::mk_v()); + superblock_disk const *sbd = reinterpret_cast(&r.data()); + superblock_traits::unpack(*sbd, sb); + + return sb; +} + +void +era::write_superblock(block_manager<>::ptr bm, superblock const &sb, block_address location) +{ + block_manager<>::write_ref w = bm->superblock_zero(location, validator::mk_v()); + superblock_traits::pack(sb, *reinterpret_cast(w.data().raw())); +} + +//---------------------------------------------------------------- diff --git a/era/superblock.h b/era/superblock.h new file mode 100644 index 0000000..5980daf --- /dev/null +++ b/era/superblock.h @@ -0,0 +1,84 @@ +#ifndef ERA_SUPERBLOCK_H +#define ERA_SUPERBLOCK_h + +#include "persistent-data/block.h" +#include "era/era_detail.h" + +#include + +//---------------------------------------------------------------- + +namespace era { + typedef unsigned char __u8; + + 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); + void clear_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_; + }; + + unsigned const SPACE_MAP_ROOT_SIZE = 128; + uint64_t const SUPERBLOCK_LOCATION = 0; + + struct superblock { + superblock(); + + uint32_t csum; + uint64_t blocknr; + superblock_flags flags; + + __u8 uuid[16]; // FIXME: do we really need this? + uint64_t magic; + uint32_t version; + + __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE]; + + uint32_t data_block_size; + uint32_t metadata_block_size; + uint32_t nr_blocks; + + uint32_t current_era; + era_detail current_detail; + + // A btree of undigested era_details + uint64_t era_root; + + // Big array holding the digested era/block info. + uint64_t era_array_root; + }; + + //-------------------------------- + + 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 const &sb, + persistent_data::block_address location = SUPERBLOCK_LOCATION); +#if 0 + void check_superblock(superblock const &sb, + superblock_damage::damage_visitor &visitor); +#endif +} + +//---------------------------------------------------------------- + +#endif