[thin_rmap] rmap_visitor
This commit is contained in:
103
thin-provisioning/rmap_visitor.cc
Normal file
103
thin-provisioning/rmap_visitor.cc
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "thin-provisioning/rmap_visitor.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace thin_provisioning;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
rmap_visitor::rmap_visitor()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
rmap_visitor::add_data_region(region const &r)
|
||||
{
|
||||
regions_.push_back(r);
|
||||
}
|
||||
|
||||
void
|
||||
rmap_visitor::visit(btree_path const &path,
|
||||
mapping_tree_detail::block_time const &bt)
|
||||
{
|
||||
if (in_regions(bt.block_)) {
|
||||
uint32_t thin_dev = path[0];
|
||||
block_address thin_block = path[1];
|
||||
|
||||
visit_block(thin_dev, thin_block, bt.block_);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rmap_visitor::complete()
|
||||
{
|
||||
if (current_rmap_)
|
||||
push_current();
|
||||
}
|
||||
|
||||
vector<rmap_visitor::rmap_region> const &
|
||||
rmap_visitor::get_rmap() const
|
||||
{
|
||||
return rmap_;
|
||||
}
|
||||
|
||||
// Slow, but I suspect we wont run with many regions.
|
||||
bool
|
||||
rmap_visitor::in_regions(block_address b) const
|
||||
{
|
||||
for (region const &r : regions_)
|
||||
if (r.contains(b))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rmap_visitor::adjacent_block(rmap_region const &rr,
|
||||
uint32_t thin_dev, block_address thin_block,
|
||||
block_address data_block) const
|
||||
{
|
||||
block_address run_length = rr.data_end - rr.data_begin;
|
||||
|
||||
return (rr.thin_dev == thin_dev) &&
|
||||
(data_block == rr.data_end) &&
|
||||
(thin_block == rr.thin_begin + run_length);
|
||||
}
|
||||
|
||||
void
|
||||
rmap_visitor::insert_new_region(uint32_t thin_dev, block_address thin_block,
|
||||
block_address data_block)
|
||||
{
|
||||
rmap_region rr;
|
||||
rr.data_begin = data_block;
|
||||
rr.data_end = data_block + 1;
|
||||
rr.thin_dev = thin_dev;
|
||||
rr.thin_begin = thin_block;
|
||||
|
||||
current_rmap_ = rr;
|
||||
}
|
||||
|
||||
void
|
||||
rmap_visitor::push_current()
|
||||
{
|
||||
rmap_.push_back(*current_rmap_);
|
||||
current_rmap_ = boost::optional<rmap_region>();
|
||||
}
|
||||
|
||||
void
|
||||
rmap_visitor::visit_block(uint32_t thin_dev, block_address thin_block,
|
||||
block_address data_block)
|
||||
{
|
||||
if (current_rmap_) {
|
||||
if (adjacent_block(*current_rmap_, thin_dev, thin_block, data_block))
|
||||
current_rmap_->data_end++;
|
||||
else {
|
||||
push_current();
|
||||
insert_new_region(thin_dev, thin_block, data_block);
|
||||
}
|
||||
|
||||
} else
|
||||
insert_new_region(thin_dev, thin_block, data_block);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
68
thin-provisioning/rmap_visitor.h
Normal file
68
thin-provisioning/rmap_visitor.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef THIN_RMAP_VISITOR_H
|
||||
#define THIN_RMAP_VISITOR_H
|
||||
|
||||
#include "persistent-data/range.h"
|
||||
#include "thin-provisioning/mapping_tree.h"
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace thin_provisioning {
|
||||
// This value visitor (see btree_damage_visitor.h) produces a
|
||||
// reverse mapping for parts of the data device.
|
||||
//
|
||||
// i) Use add_data_region() to specify which areas of the data device you're interested in.
|
||||
// ii) visit the mapping tree
|
||||
// iii) call complete()
|
||||
// iv) get the rmaps with get_rmap();
|
||||
class rmap_visitor {
|
||||
public:
|
||||
typedef range<block_address> region;
|
||||
|
||||
rmap_visitor();
|
||||
|
||||
// Specify which regions of the data device you want the rmap for.
|
||||
void add_data_region(region const &r);
|
||||
void visit(btree_path const &path, mapping_tree_detail::block_time const &bt);
|
||||
|
||||
struct rmap_region {
|
||||
// FIXME: surely we don't need to provide this for
|
||||
// a POD structure?
|
||||
bool operator ==(rmap_region const &rhs) const {
|
||||
return ((data_begin == rhs.data_begin) &&
|
||||
(data_end == rhs.data_end) &&
|
||||
(thin_dev == rhs.thin_dev) &&
|
||||
(thin_begin == rhs.thin_begin));
|
||||
}
|
||||
|
||||
block_address data_begin;
|
||||
block_address data_end;
|
||||
|
||||
uint32_t thin_dev;
|
||||
block_address thin_begin;
|
||||
};
|
||||
|
||||
void complete();
|
||||
vector<rmap_region> const &get_rmap() const;
|
||||
|
||||
private:
|
||||
bool in_regions(block_address b) const;
|
||||
bool adjacent_block(rmap_region const &rr,
|
||||
uint32_t thin_dev, block_address thin_block,
|
||||
block_address data_block) const;
|
||||
void insert_new_region(uint32_t thin_dev, block_address thin_block,
|
||||
block_address data_block);
|
||||
void push_current();
|
||||
|
||||
void visit_block(uint32_t thin_dev, block_address thin_block,
|
||||
block_address data_block);
|
||||
|
||||
vector<region> regions_;
|
||||
|
||||
boost::optional<rmap_region> current_rmap_;
|
||||
vector<rmap_region> rmap_;
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user