Merge branch 'era' of github.com:jthornber/thin-provisioning-tools into era
This commit is contained in:
commit
e1e9e34a55
112
era/bloom_tree.h
Normal file
112
era/bloom_tree.h
Normal 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 ¤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<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
118
era/superblock.cc
Normal 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
84
era/superblock.h
Normal 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
|
Loading…
Reference in New Issue
Block a user