Merge branch 'era' of github.com:jthornber/thin-provisioning-tools into era

This commit is contained in:
Joe Thornber 2014-01-08 10:53:44 +00:00
commit e1e9e34a55
3 changed files with 314 additions and 0 deletions

112
era/bloom_tree.h Normal file
View File

@ -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<block_address> 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 &current_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<block_address &result) const {
for (block_address b = 0; b < nr_blocks; b++)
if (f.test(b))
result.insert(b);
}
private:
static unsigned power_bits(block_address nr_blocks) {
// We're expecting 1% of the cache to change per era
block_address expected_writes = nr_blocks / 100;
unsigned r = 1;
while ((1ull << r) < (16 * expected_writes))
r++;
return r;
}
typedef bloom_filter<block_address_bloom_traits> 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<bool> base_;
deque<era_details> eras_;
};
#endif

118
era/superblock.cc Normal file
View File

@ -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<superblock_disk const *>(&b);
crc32c sum(SUPERBLOCK_CSUM_SEED);
sum.append(&sbd->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
if (sum.get_sum() != to_cpu<uint32_t>(sbd->csum))
throw checksum_error("bad checksum in superblock");
}
virtual void prepare(buffer<> &b, block_address location) const {
superblock_disk *sbd = reinterpret_cast<superblock_disk *>(&b);
crc32c sum(SUPERBLOCK_CSUM_SEED);
sum.append(&sbd->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
sbd->csum = to_disk<base::le32>(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<superblock_disk const *>(&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<superblock_disk *>(w.data().raw()));
}
//----------------------------------------------------------------

84
era/superblock.h Normal file
View File

@ -0,0 +1,84 @@
#ifndef ERA_SUPERBLOCK_H
#define ERA_SUPERBLOCK_h
#include "persistent-data/block.h"
#include "era/era_detail.h"
#include <set>
//----------------------------------------------------------------
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<flag> 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