Introduce mapping_tree.h
This commit is contained in:
parent
35880f3038
commit
8f2ab2d676
107
thin-provisioning/mapping_tree.h
Normal file
107
thin-provisioning/mapping_tree.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#ifndef MAPPING_TREE_H
|
||||||
|
#define MAPPING_TREE_H
|
||||||
|
|
||||||
|
#include "persistent-data/data-structures/btree.h"
|
||||||
|
#include "persistent-data/range.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace thin_provisioning {
|
||||||
|
namespace mapping_tree_detail {
|
||||||
|
class space_map_ref_counter {
|
||||||
|
public:
|
||||||
|
space_map_ref_counter(space_map::ptr sm)
|
||||||
|
: sm_(sm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void inc(block_address b) {
|
||||||
|
sm_->inc(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dec(block_address b) {
|
||||||
|
sm_->dec(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
space_map::ptr sm_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct block_time {
|
||||||
|
uint64_t block_;
|
||||||
|
uint32_t time_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class block_time_ref_counter {
|
||||||
|
public:
|
||||||
|
block_time_ref_counter(space_map::ptr sm)
|
||||||
|
: sm_(sm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void inc(block_time bt) {
|
||||||
|
sm_->inc(bt.block_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dec(block_time bt) {
|
||||||
|
sm_->dec(bt.block_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
space_map::ptr sm_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct block_traits {
|
||||||
|
typedef base::le64 disk_type;
|
||||||
|
typedef block_time value_type;
|
||||||
|
typedef block_time_ref_counter ref_counter;
|
||||||
|
|
||||||
|
static void unpack(disk_type const &disk, value_type &value) {
|
||||||
|
uint64_t v = to_cpu<uint64_t>(disk);
|
||||||
|
value.block_ = v >> 24;
|
||||||
|
value.time_ = v & ((1 << 24) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pack(value_type const &value, disk_type &disk) {
|
||||||
|
uint64_t v = (value.block_ << 24) | value.time_;
|
||||||
|
disk = base::to_disk<base::le64>(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class mtree_ref_counter {
|
||||||
|
public:
|
||||||
|
mtree_ref_counter(transaction_manager::ptr tm)
|
||||||
|
: tm_(tm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void inc(block_address b) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void dec(block_address b) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
transaction_manager::ptr tm_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mtree_traits {
|
||||||
|
typedef base::le64 disk_type;
|
||||||
|
typedef uint64_t value_type;
|
||||||
|
typedef mtree_ref_counter ref_counter;
|
||||||
|
|
||||||
|
static void unpack(disk_type const &disk, value_type &value) {
|
||||||
|
value = base::to_cpu<uint64_t>(disk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pack(value_type const &value, disk_type &disk) {
|
||||||
|
disk = base::to_disk<base::le64>(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef persistent_data::btree<2, mapping_tree_detail::block_traits> mapping_tree;
|
||||||
|
typedef persistent_data::btree<1, mapping_tree_detail::mtree_traits> dev_tree;
|
||||||
|
typedef persistent_data::btree<1, mapping_tree_detail::block_traits> single_mapping_tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
@ -108,8 +108,10 @@ metadata::metadata(std::string const &dev_path, open_type ot,
|
|||||||
|
|
||||||
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_));
|
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_));
|
||||||
details_ = device_tree::ptr(new device_tree(tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter()));
|
details_ = device_tree::ptr(new device_tree(tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter()));
|
||||||
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_, mtree_ref_counter(tm_)));
|
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_,
|
||||||
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_, block_time_ref_counter(data_sm_)));
|
mapping_tree_detail::mtree_ref_counter(tm_)));
|
||||||
|
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_,
|
||||||
|
mapping_tree_detail::block_time_ref_counter(data_sm_)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CREATE:
|
case CREATE:
|
||||||
@ -121,8 +123,10 @@ metadata::metadata(std::string const &dev_path, open_type ot,
|
|||||||
|
|
||||||
data_sm_ = create_disk_sm(tm_, nr_data_blocks);
|
data_sm_ = create_disk_sm(tm_, nr_data_blocks);
|
||||||
details_ = device_tree::ptr(new device_tree(tm_, device_tree_detail::device_details_traits::ref_counter()));
|
details_ = device_tree::ptr(new device_tree(tm_, device_tree_detail::device_details_traits::ref_counter()));
|
||||||
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, block_time_ref_counter(data_sm_)));
|
mappings_ = mapping_tree::ptr(new mapping_tree(tm_,
|
||||||
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, mappings_->get_root(), mtree_ref_counter(tm_)));
|
mapping_tree_detail::block_time_ref_counter(data_sm_)));
|
||||||
|
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, mappings_->get_root(),
|
||||||
|
mapping_tree_detail::mtree_ref_counter(tm_)));
|
||||||
|
|
||||||
::memset(&sb_, 0, sizeof(sb_));
|
::memset(&sb_, 0, sizeof(sb_));
|
||||||
sb_.magic_ = SUPERBLOCK_MAGIC;
|
sb_.magic_ = SUPERBLOCK_MAGIC;
|
||||||
@ -147,8 +151,10 @@ metadata::metadata(std::string const &dev_path, block_address metadata_snap)
|
|||||||
|
|
||||||
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_));
|
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_));
|
||||||
details_ = device_tree::ptr(new device_tree(tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter()));
|
details_ = device_tree::ptr(new device_tree(tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter()));
|
||||||
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_, mtree_ref_counter(tm_)));
|
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_,
|
||||||
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_, block_time_ref_counter(data_sm_)));
|
mapping_tree_detail::mtree_ref_counter(tm_)));
|
||||||
|
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_,
|
||||||
|
mapping_tree_detail::block_time_ref_counter(data_sm_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: duplication
|
// FIXME: duplication
|
||||||
@ -169,8 +175,10 @@ metadata::metadata(block_manager<>::ptr bm, open_type ot,
|
|||||||
|
|
||||||
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_));
|
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_));
|
||||||
details_ = device_tree::ptr(new device_tree(tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter()));
|
details_ = device_tree::ptr(new device_tree(tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter()));
|
||||||
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_, mtree_ref_counter(tm_)));
|
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_,
|
||||||
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_, block_time_ref_counter(data_sm_)));
|
mapping_tree_detail::mtree_ref_counter(tm_)));
|
||||||
|
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_,
|
||||||
|
mapping_tree_detail::block_time_ref_counter(data_sm_)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CREATE:
|
case CREATE:
|
||||||
@ -182,8 +190,10 @@ metadata::metadata(block_manager<>::ptr bm, open_type ot,
|
|||||||
|
|
||||||
data_sm_ = create_disk_sm(tm_, nr_data_blocks);
|
data_sm_ = create_disk_sm(tm_, nr_data_blocks);
|
||||||
details_ = device_tree::ptr(new device_tree(tm_, device_tree_detail::device_details_traits::ref_counter()));
|
details_ = device_tree::ptr(new device_tree(tm_, device_tree_detail::device_details_traits::ref_counter()));
|
||||||
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, block_time_ref_counter(data_sm_)));
|
mappings_ = mapping_tree::ptr(new mapping_tree(tm_,
|
||||||
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, mappings_->get_root(), mtree_ref_counter(tm_)));
|
mapping_tree_detail::block_time_ref_counter(data_sm_)));
|
||||||
|
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, mappings_->get_root(),
|
||||||
|
mapping_tree_detail::mtree_ref_counter(tm_)));
|
||||||
|
|
||||||
::memset(&sb_, 0, sizeof(sb_));
|
::memset(&sb_, 0, sizeof(sb_));
|
||||||
sb_.magic_ = SUPERBLOCK_MAGIC;
|
sb_.magic_ = SUPERBLOCK_MAGIC;
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "thin-provisioning/metadata_disk_structures.h"
|
#include "thin-provisioning/metadata_disk_structures.h"
|
||||||
#include "thin-provisioning/device_tree.h"
|
#include "thin-provisioning/device_tree.h"
|
||||||
|
#include "thin-provisioning/mapping_tree.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
@ -40,101 +41,8 @@ namespace thin_provisioning {
|
|||||||
|
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
|
|
||||||
class space_map_ref_counter {
|
|
||||||
public:
|
|
||||||
space_map_ref_counter(space_map::ptr sm)
|
|
||||||
: sm_(sm) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void inc(block_address b) {
|
|
||||||
sm_->inc(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dec(block_address b) {
|
|
||||||
sm_->dec(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
space_map::ptr sm_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct block_time {
|
|
||||||
uint64_t block_;
|
|
||||||
uint32_t time_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class block_time_ref_counter {
|
|
||||||
public:
|
|
||||||
block_time_ref_counter(space_map::ptr sm)
|
|
||||||
: sm_(sm) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void inc(block_time bt) {
|
|
||||||
sm_->inc(bt.block_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dec(block_time bt) {
|
|
||||||
sm_->dec(bt.block_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
space_map::ptr sm_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct block_traits {
|
|
||||||
typedef base::le64 disk_type;
|
|
||||||
typedef block_time value_type;
|
|
||||||
typedef block_time_ref_counter ref_counter;
|
|
||||||
|
|
||||||
static void unpack(disk_type const &disk, value_type &value) {
|
|
||||||
uint64_t v = to_cpu<uint64_t>(disk);
|
|
||||||
value.block_ = v >> 24;
|
|
||||||
value.time_ = v & ((1 << 24) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pack(value_type const &value, disk_type &disk) {
|
|
||||||
uint64_t v = (value.block_ << 24) | value.time_;
|
|
||||||
disk = base::to_disk<base::le64>(v);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------
|
|
||||||
|
|
||||||
class mtree_ref_counter {
|
|
||||||
public:
|
|
||||||
mtree_ref_counter(transaction_manager::ptr tm)
|
|
||||||
: tm_(tm) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void inc(block_address b) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void dec(block_address b) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
transaction_manager::ptr tm_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mtree_traits {
|
|
||||||
typedef base::le64 disk_type;
|
|
||||||
typedef uint64_t value_type;
|
|
||||||
typedef mtree_ref_counter ref_counter;
|
|
||||||
|
|
||||||
static void unpack(disk_type const &disk, value_type &value) {
|
|
||||||
value = base::to_cpu<uint64_t>(disk);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pack(value_type const &value, disk_type &disk) {
|
|
||||||
disk = base::to_disk<base::le64>(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// FIXME: should these be in a sub-namespace?
|
// FIXME: should these be in a sub-namespace?
|
||||||
typedef persistent_data::transaction_manager::ptr tm_ptr;
|
typedef persistent_data::transaction_manager::ptr tm_ptr;
|
||||||
typedef persistent_data::btree<1, mtree_traits> dev_tree;
|
|
||||||
typedef persistent_data::btree<2, block_traits> mapping_tree;
|
|
||||||
typedef persistent_data::btree<1, block_traits> single_mapping_tree;
|
|
||||||
|
|
||||||
// The tools require different interfaces onto the metadata than
|
// The tools require different interfaces onto the metadata than
|
||||||
// the in kernel driver. This class gives access to the low-level
|
// the in kernel driver. This class gives access to the low-level
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "metadata_dumper.h"
|
#include "metadata_dumper.h"
|
||||||
|
#include "thin-provisioning/mapping_tree.h"
|
||||||
|
|
||||||
using namespace persistent_data;
|
using namespace persistent_data;
|
||||||
using namespace thin_provisioning;
|
using namespace thin_provisioning;
|
||||||
@ -24,11 +25,11 @@ using namespace thin_provisioning;
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class mappings_extractor : public btree<2, block_traits>::visitor {
|
class mappings_extractor : public mapping_tree::visitor {
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<mappings_extractor> ptr;
|
typedef boost::shared_ptr<mappings_extractor> ptr;
|
||||||
typedef btree_detail::node_location node_location;
|
typedef btree_detail::node_location node_location;
|
||||||
typedef btree_checker<2, block_traits> checker;
|
typedef btree_checker<2, mapping_tree_detail::block_traits> checker;
|
||||||
|
|
||||||
mappings_extractor(uint64_t dev_id, emitter::ptr e,
|
mappings_extractor(uint64_t dev_id, emitter::ptr e,
|
||||||
space_map::ptr md_sm, space_map::ptr data_sm)
|
space_map::ptr md_sm, space_map::ptr data_sm)
|
||||||
@ -64,14 +65,14 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool visit_leaf(node_location const &loc,
|
bool visit_leaf(node_location const &loc,
|
||||||
btree_detail::node_ref<block_traits> const &n) {
|
btree_detail::node_ref<mapping_tree_detail::block_traits> const &n) {
|
||||||
if (!checker_.visit_leaf(loc, n)) {
|
if (!checker_.visit_leaf(loc, n)) {
|
||||||
found_errors_ = true;
|
found_errors_ = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < n.get_nr_entries(); i++) {
|
for (unsigned i = 0; i < n.get_nr_entries(); i++) {
|
||||||
block_time bt = n.value_at(i);
|
mapping_tree_detail::block_time bt = n.value_at(i);
|
||||||
add_mapping(n.key_at(i), bt.block_, bt.time_);
|
add_mapping(n.key_at(i), bt.block_, bt.time_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ namespace {
|
|||||||
throw runtime_error("not in device");
|
throw runtime_error("not in device");
|
||||||
|
|
||||||
uint64_t key[1] = {origin_block};
|
uint64_t key[1] = {origin_block};
|
||||||
block_time bt;
|
mapping_tree_detail::block_time bt;
|
||||||
bt.block_ = data_block;
|
bt.block_ = data_block;
|
||||||
bt.time_ = time;
|
bt.time_ = time;
|
||||||
current_mapping_->insert(key, bt);
|
current_mapping_->insert(key, bt);
|
||||||
@ -125,7 +125,7 @@ namespace {
|
|||||||
single_mapping_tree::ptr new_mapping_tree() {
|
single_mapping_tree::ptr new_mapping_tree() {
|
||||||
return single_mapping_tree::ptr(
|
return single_mapping_tree::ptr(
|
||||||
new single_mapping_tree(md_->tm_,
|
new single_mapping_tree(md_->tm_,
|
||||||
block_time_ref_counter(md_->data_sm_)));
|
mapping_tree_detail::block_time_ref_counter(md_->data_sm_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool device_exists(thin_dev_t dev) const {
|
bool device_exists(thin_dev_t dev) const {
|
||||||
|
@ -56,7 +56,7 @@ void
|
|||||||
thin::insert(block_address thin_block, block_address data_block)
|
thin::insert(block_address thin_block, block_address data_block)
|
||||||
{
|
{
|
||||||
uint64_t key[2] = {dev_, thin_block};
|
uint64_t key[2] = {dev_, thin_block};
|
||||||
block_time bt;
|
mapping_tree_detail::block_time bt;
|
||||||
bt.block_ = data_block;
|
bt.block_ = data_block;
|
||||||
bt.time_ = 0; // FIXME: use current time.
|
bt.time_ = 0; // FIXME: use current time.
|
||||||
return pool_->md_->mappings_->insert(key, bt);
|
return pool_->md_->mappings_->insert(key, bt);
|
||||||
@ -124,7 +124,8 @@ thin_pool::create_thin(thin_dev_t dev)
|
|||||||
if (device_exists(dev))
|
if (device_exists(dev))
|
||||||
throw std::runtime_error("Device already exists");
|
throw std::runtime_error("Device already exists");
|
||||||
|
|
||||||
single_mapping_tree::ptr new_tree(new single_mapping_tree(md_->tm_, block_time_ref_counter(md_->data_sm_)));
|
single_mapping_tree::ptr new_tree(new single_mapping_tree(md_->tm_,
|
||||||
|
mapping_tree_detail::block_time_ref_counter(md_->data_sm_)));
|
||||||
md_->mappings_top_level_->insert(key, new_tree->get_root());
|
md_->mappings_top_level_->insert(key, new_tree->get_root());
|
||||||
md_->mappings_->set_root(md_->mappings_top_level_->get_root()); // FIXME: ugly
|
md_->mappings_->set_root(md_->mappings_top_level_->get_root()); // FIXME: ugly
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ thin_pool::create_snap(thin_dev_t dev, thin_dev_t origin)
|
|||||||
throw std::runtime_error("unknown origin");
|
throw std::runtime_error("unknown origin");
|
||||||
|
|
||||||
single_mapping_tree otree(md_->tm_, *mtree_root,
|
single_mapping_tree otree(md_->tm_, *mtree_root,
|
||||||
block_time_ref_counter(md_->data_sm_));
|
mapping_tree_detail::block_time_ref_counter(md_->data_sm_));
|
||||||
|
|
||||||
single_mapping_tree::ptr clone(otree.clone());
|
single_mapping_tree::ptr clone(otree.clone());
|
||||||
md_->mappings_top_level_->insert(snap_key, clone->get_root());
|
md_->mappings_top_level_->insert(snap_key, clone->get_root());
|
||||||
|
@ -35,7 +35,7 @@ namespace thin_provisioning {
|
|||||||
class thin {
|
class thin {
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<thin> ptr;
|
typedef boost::shared_ptr<thin> ptr;
|
||||||
typedef boost::optional<block_time> maybe_address;
|
typedef boost::optional<mapping_tree_detail::block_time> maybe_address;
|
||||||
|
|
||||||
thin_dev_t get_dev_t() const;
|
thin_dev_t get_dev_t() const;
|
||||||
maybe_address lookup(block_address thin_block);
|
maybe_address lookup(block_address thin_block);
|
||||||
|
Loading…
Reference in New Issue
Block a user