check metadata reference counts
This commit is contained in:
parent
dfe3275eac
commit
52f03b7542
@ -29,6 +29,13 @@ error_set::add_child(error_set::ptr err)
|
|||||||
children_.push_back(err);
|
children_.push_back(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
error_set::add_child(boost::optional<error_set::ptr> maybe_errs)
|
||||||
|
{
|
||||||
|
if (maybe_errs)
|
||||||
|
children_.push_back(*maybe_errs);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
error_set::add_child(string const &err)
|
error_set::add_child(string const &err)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef ERROR_SET_H
|
#ifndef ERROR_SET_H
|
||||||
#define ERROR_SET_H
|
#define ERROR_SET_H
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
@ -22,6 +23,7 @@ namespace persistent_data {
|
|||||||
std::string const &get_description() const;
|
std::string const &get_description() const;
|
||||||
std::list<error_set::ptr> const &get_children() const;
|
std::list<error_set::ptr> const &get_children() const;
|
||||||
void add_child(error_set::ptr err);
|
void add_child(error_set::ptr err);
|
||||||
|
void add_child(boost::optional<error_set::ptr> maybe_errs);
|
||||||
void add_child(std::string const &err);
|
void add_child(std::string const &err);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
52
metadata.cc
52
metadata.cc
@ -182,6 +182,7 @@ thin::set_mapped_blocks(block_address count)
|
|||||||
metadata::metadata(std::string const &dev_path)
|
metadata::metadata(std::string const &dev_path)
|
||||||
: tm_(open_tm(dev_path)),
|
: tm_(open_tm(dev_path)),
|
||||||
sb_(read_superblock(tm_->get_bm())),
|
sb_(read_superblock(tm_->get_bm())),
|
||||||
|
metadata_sm_(open_metadata_sm<MD_BLOCK_SIZE>(tm_, static_cast<void *>(&sb_.metadata_space_map_root_))),
|
||||||
data_sm_(open_disk_sm<MD_BLOCK_SIZE>(tm_, static_cast<void *>(&sb_.data_space_map_root_))),
|
data_sm_(open_disk_sm<MD_BLOCK_SIZE>(tm_, static_cast<void *>(&sb_.data_space_map_root_))),
|
||||||
details_(tm_, sb_.device_details_root_, device_details_traits::ref_counter()),
|
details_(tm_, sb_.device_details_root_, device_details_traits::ref_counter()),
|
||||||
mappings_top_level_(tm_, sb_.data_mapping_root_, mtree_ref_counter<MD_BLOCK_SIZE>(tm_)),
|
mappings_top_level_(tm_, sb_.data_mapping_root_, mtree_ref_counter<MD_BLOCK_SIZE>(tm_)),
|
||||||
@ -326,6 +327,32 @@ metadata::device_exists(thin_dev_t dev) const
|
|||||||
return details_.lookup(key);
|
return details_.lookup(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// FIXME: this doesn't check for non-zero counts in the sm that are
|
||||||
|
// actually zero.
|
||||||
|
optional<error_set::ptr>
|
||||||
|
check_ref_counts(string const &desc, block_counter const &actual,
|
||||||
|
space_map::ptr sm) {
|
||||||
|
error_set::ptr errors(new error_set(desc));
|
||||||
|
|
||||||
|
bool bad = false;
|
||||||
|
block_counter::count_map const &counts = actual.get_counts();
|
||||||
|
block_counter::count_map::const_iterator it, end = counts.end();
|
||||||
|
for (it = counts.begin(); it != end; ++it) {
|
||||||
|
uint32_t ref_count = sm->get_count(it->first);
|
||||||
|
if (ref_count != it->second) {
|
||||||
|
ostringstream out;
|
||||||
|
out << it->first << ": was " << ref_count
|
||||||
|
<< ", expected " << it->second;
|
||||||
|
errors->add_child(out.str());
|
||||||
|
bad = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bad ? optional<error_set::ptr>(errors) : optional<error_set::ptr>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boost::optional<error_set::ptr>
|
boost::optional<error_set::ptr>
|
||||||
metadata::check()
|
metadata::check()
|
||||||
{
|
{
|
||||||
@ -351,27 +378,10 @@ metadata::check()
|
|||||||
}
|
}
|
||||||
|
|
||||||
data_sm_->check(metadata_counter);
|
data_sm_->check(metadata_counter);
|
||||||
|
errors->add_child(check_ref_counts("Errors in metadata block reference counts",
|
||||||
{
|
metadata_counter, metadata_sm_));
|
||||||
error_set::ptr data_errors(new error_set("Errors in data reference counts"));
|
errors->add_child(check_ref_counts("Errors in data block reference counts",
|
||||||
|
data_counter, data_sm_));
|
||||||
bool bad = false;
|
|
||||||
block_counter::count_map const &data_counts = data_counter.get_counts();
|
|
||||||
for (block_counter::count_map::const_iterator it = data_counts.begin();
|
|
||||||
it != data_counts.end(); ++it) {
|
|
||||||
uint32_t ref_count = data_sm_->get_count(it->first);
|
|
||||||
if (ref_count != it->second) {
|
|
||||||
ostringstream out;
|
|
||||||
out << it->first << ": was " << ref_count
|
|
||||||
<< ", expected " << it->second;
|
|
||||||
data_errors->add_child(out.str());
|
|
||||||
bad = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bad)
|
|
||||||
errors->add_child(data_errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (errors->get_children().size() > 0) ?
|
return (errors->get_children().size() > 0) ?
|
||||||
optional<error_set::ptr>(errors) :
|
optional<error_set::ptr>(errors) :
|
||||||
|
@ -192,8 +192,7 @@ namespace thin_provisioning {
|
|||||||
tm_ptr tm_;
|
tm_ptr tm_;
|
||||||
superblock sb_;
|
superblock sb_;
|
||||||
|
|
||||||
// Ignoring the metadata sm for now, since we don't need it for the basic 'dump' tool
|
space_map::ptr metadata_sm_;
|
||||||
// space_map::ptr metadata_sm_;
|
|
||||||
sm_disk_detail::sm_disk<MD_BLOCK_SIZE>::ptr data_sm_;
|
sm_disk_detail::sm_disk<MD_BLOCK_SIZE>::ptr data_sm_;
|
||||||
detail_tree details_;
|
detail_tree details_;
|
||||||
dev_tree mappings_top_level_;
|
dev_tree mappings_top_level_;
|
||||||
|
110
space_map_disk.h
110
space_map_disk.h
@ -175,6 +175,7 @@ namespace persistent_data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void commit() {
|
void commit() {
|
||||||
|
commit_ies();
|
||||||
}
|
}
|
||||||
|
|
||||||
void inc(block_address b) {
|
void inc(block_address b) {
|
||||||
@ -252,9 +253,10 @@ namespace persistent_data {
|
|||||||
private:
|
private:
|
||||||
virtual index_entry find_ie(block_address b) const = 0;
|
virtual index_entry find_ie(block_address b) const = 0;
|
||||||
virtual void save_ie(block_address b, struct index_entry ie) = 0;
|
virtual void save_ie(block_address b, struct index_entry ie) = 0;
|
||||||
|
virtual void commit_ies() = 0;
|
||||||
|
|
||||||
ref_t lookup_bitmap(block_address b) const {
|
ref_t lookup_bitmap(block_address b) const {
|
||||||
index_entry ie = find_ie(b);
|
index_entry ie = find_ie(b / entries_per_block_);
|
||||||
bitmap<BlockSize> bm(tm_, ie);
|
bitmap<BlockSize> bm(tm_, ie);
|
||||||
return bm.lookup(b % entries_per_block_);
|
return bm.lookup(b % entries_per_block_);
|
||||||
}
|
}
|
||||||
@ -263,7 +265,7 @@ namespace persistent_data {
|
|||||||
if (n > 3)
|
if (n > 3)
|
||||||
throw runtime_error("bitmap can only hold 2 bit values");
|
throw runtime_error("bitmap can only hold 2 bit values");
|
||||||
|
|
||||||
index_entry ie = find_ie(b);
|
index_entry ie = find_ie(b / entries_per_block_);
|
||||||
bitmap<BlockSize> bm(tm_, ie);
|
bitmap<BlockSize> bm(tm_, ie);
|
||||||
bm.insert(b % entries_per_block_, n);
|
bm.insert(b % entries_per_block_, n);
|
||||||
save_ie(b, bm.get_ie());
|
save_ie(b, bm.get_ie());
|
||||||
@ -346,8 +348,8 @@ namespace persistent_data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
index_entry find_ie(block_address b) const {
|
index_entry find_ie(block_address ie_index) const {
|
||||||
uint64_t key[1] = {b / sm_disk_base<BlockSize>::get_entries_per_block()};
|
uint64_t key[1] = {ie_index};
|
||||||
optional<index_entry> mindex = bitmaps_.lookup(key);
|
optional<index_entry> mindex = bitmaps_.lookup(key);
|
||||||
if (!mindex)
|
if (!mindex)
|
||||||
throw runtime_error("Couldn't lookup bitmap");
|
throw runtime_error("Couldn't lookup bitmap");
|
||||||
@ -355,13 +357,93 @@ namespace persistent_data {
|
|||||||
return *mindex;
|
return *mindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_ie(block_address b, struct index_entry ie) {
|
void save_ie(block_address ie_index, struct index_entry ie) {
|
||||||
uint64_t key[1] = {b / sm_disk_base<BlockSize>::get_entries_per_block()};
|
uint64_t key[1] = {ie_index};
|
||||||
bitmaps_.insert(key, ie);
|
bitmaps_.insert(key, ie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void commit_ies() {
|
||||||
|
}
|
||||||
|
|
||||||
btree<1, index_entry_traits, BlockSize> bitmaps_;
|
btree<1, index_entry_traits, BlockSize> bitmaps_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <uint32_t BlockSize>
|
||||||
|
class sm_metadata : public sm_disk_base<BlockSize> {
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<sm_metadata<BlockSize> > ptr;
|
||||||
|
|
||||||
|
sm_metadata(typename transaction_manager<BlockSize>::ptr tm)
|
||||||
|
: sm_disk_base<BlockSize>(tm),
|
||||||
|
entries_(MAX_METADATA_BITMAPS) {
|
||||||
|
// FIXME: allocate a new bitmap root
|
||||||
|
}
|
||||||
|
|
||||||
|
sm_metadata(typename transaction_manager<BlockSize>::ptr tm,
|
||||||
|
sm_root const &root)
|
||||||
|
: sm_disk_base<BlockSize>(tm, root),
|
||||||
|
bitmap_root_(root.bitmap_root_),
|
||||||
|
entries_(MAX_METADATA_BITMAPS) {
|
||||||
|
load_ies();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t root_size() {
|
||||||
|
return sizeof(sm_root_disk);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: common code
|
||||||
|
void copy_root(void *dest, size_t len) {
|
||||||
|
sm_root_disk d;
|
||||||
|
sm_root v;
|
||||||
|
|
||||||
|
if (len < sizeof(d))
|
||||||
|
throw runtime_error("root too small");
|
||||||
|
|
||||||
|
v.nr_blocks_ = sm_disk_base<BlockSize>::get_nr_blocks();
|
||||||
|
v.nr_allocated_ = sm_disk_base<BlockSize>::get_nr_allocated();
|
||||||
|
v.bitmap_root_ = bitmap_root_;
|
||||||
|
v.ref_count_root_ = sm_disk_base<BlockSize>::get_ref_count_root();
|
||||||
|
sm_root_traits::pack(v, d);
|
||||||
|
::memcpy(dest, &d, sizeof(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
index_entry find_ie(block_address ie_index) const {
|
||||||
|
return entries_[ie_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_ie(block_address ie_index, struct index_entry ie) {
|
||||||
|
entries_[ie_index] = ie;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_ies() {
|
||||||
|
typename block_manager<BlockSize>::read_ref rr =
|
||||||
|
sm_disk_base<BlockSize>::get_tm()->read_lock(bitmap_root_);
|
||||||
|
|
||||||
|
metadata_index const *mdi = reinterpret_cast<metadata_index const *>(&rr.data());
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < MAX_METADATA_BITMAPS; i++)
|
||||||
|
index_entry_traits::unpack(*(mdi->index + i), entries_[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void commit_ies() {
|
||||||
|
std::pair<typename block_manager<BlockSize>::write_ref, bool> p =
|
||||||
|
sm_disk_base<BlockSize>::get_tm()->shadow(bitmap_root_);
|
||||||
|
|
||||||
|
bitmap_root_ = p.first.get_location();
|
||||||
|
metadata_index *mdi = reinterpret_cast<metadata_index *>(&p.first.data());
|
||||||
|
|
||||||
|
mdi->csum_ = to_disk<__le32, uint32_t>(0);
|
||||||
|
mdi->padding_ = to_disk<__le32, uint32_t>(0);
|
||||||
|
mdi->blocknr_ = to_disk<__le64>(bitmap_root_);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < entries_.size(); i++)
|
||||||
|
index_entry_traits::pack(entries_[i], mdi->index[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
block_address bitmap_root_;
|
||||||
|
std::vector<index_entry> entries_;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t MetadataBlockSize>
|
template <uint32_t MetadataBlockSize>
|
||||||
@ -391,6 +473,22 @@ namespace persistent_data {
|
|||||||
return typename sm_disk<MetadataBlockSize>::ptr(
|
return typename sm_disk<MetadataBlockSize>::ptr(
|
||||||
new sm_disk<MetadataBlockSize>(tm, v));
|
new sm_disk<MetadataBlockSize>(tm, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <uint32_t MetadataBlockSize>
|
||||||
|
typename sm_disk_detail::sm_metadata<MetadataBlockSize>::ptr
|
||||||
|
open_metadata_sm(typename transaction_manager<MetadataBlockSize>::ptr tm,
|
||||||
|
void * root)
|
||||||
|
{
|
||||||
|
using namespace sm_disk_detail;
|
||||||
|
|
||||||
|
sm_root_disk d;
|
||||||
|
sm_root v;
|
||||||
|
|
||||||
|
::memcpy(&d, root, sizeof(d));
|
||||||
|
sm_root_traits::unpack(d, v);
|
||||||
|
return typename sm_metadata<MetadataBlockSize>::ptr(
|
||||||
|
new sm_metadata<MetadataBlockSize>(tm, v));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -48,7 +48,7 @@ namespace persistent_data {
|
|||||||
__le32 padding_;
|
__le32 padding_;
|
||||||
__le64 blocknr_;
|
__le64 blocknr_;
|
||||||
|
|
||||||
struct index_entry index[MAX_METADATA_BITMAPS];
|
struct index_entry_disk index[MAX_METADATA_BITMAPS];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct sm_root_disk {
|
struct sm_root_disk {
|
||||||
|
Loading…
Reference in New Issue
Block a user