[thin_show_dups] Support fractions of a pool block size

This commit is contained in:
Joe Thornber 2015-09-08 17:09:41 +01:00
parent c58c15e788
commit 664841ad03
4 changed files with 180 additions and 15 deletions

View File

@ -75,6 +75,7 @@ SOURCE=\
thin-provisioning/cache_stream.cc \ thin-provisioning/cache_stream.cc \
thin-provisioning/chunk_stream.cc \ thin-provisioning/chunk_stream.cc \
thin-provisioning/device_tree.cc \ thin-provisioning/device_tree.cc \
thin-provisioning/fixed_chunk_stream.cc \
thin-provisioning/human_readable_format.cc \ thin-provisioning/human_readable_format.cc \
thin-provisioning/mapping_tree.cc \ thin-provisioning/mapping_tree.cc \
thin-provisioning/metadata.cc \ thin-provisioning/metadata.cc \

View File

@ -0,0 +1,113 @@
#include "thin-provisioning/fixed_chunk_stream.h"
using namespace thin_provisioning;
//----------------------------------------------------------------
fixed_chunk_stream::fixed_chunk_stream(chunk_stream &stream, unsigned chunk_size)
: index_(0),
stream_(stream),
chunk_size_(chunk_size),
big_chunk_(0) {
next_big_chunk();
}
fixed_chunk_stream::~fixed_chunk_stream()
{
put_big_chunk();
}
bcache::block_address
fixed_chunk_stream::size() const
{
return stream_.size();
}
void
fixed_chunk_stream::rewind()
{
// FIXME: not complete
index_ = 0;
stream_.rewind();
}
bool
fixed_chunk_stream::next(bcache::block_address count)
{
while (count--) {
index_++;
advance_one();
}
return !eof();
}
bool
fixed_chunk_stream::eof() const
{
return stream_.eof();
}
chunk const &
fixed_chunk_stream::get()
{
assert(big_chunk_);
little_chunk_.len_ = little_e_ - little_b_;
little_chunk_.offset_ = big_chunk_->offset_ + little_chunk_.len_;
little_chunk_.mem_.begin = little_b_;
little_chunk_.mem_.end = little_e_;
return little_chunk_;
}
void
fixed_chunk_stream::put(chunk const &c)
{
// noop
}
bool
fixed_chunk_stream::next_big_chunk()
{
put_big_chunk();
if (!stream_.next())
return false;
big_chunk_ = &stream_.get();
little_b_ = little_e_ = last_hashed_ = big_chunk_->mem_.begin;
return true;
}
bool
fixed_chunk_stream::advance_one()
{
uint8_t *big_e;
big_e = big_chunk_->mem_.end;
little_b_ = little_e_;
if (little_b_ >= big_e) {
if (next_big_chunk())
big_e = big_chunk_->mem_.end;
else
return false;
}
little_e_ += chunk_size_;
return true;
}
void
fixed_chunk_stream::put_big_chunk()
{
if (big_chunk_)
stream_.put(*big_chunk_);
big_chunk_ = 0;
}
//----------------------------------------------------------------

View File

@ -0,0 +1,39 @@
#ifndef THIN_PROVISIONING_FIXED_CHUNK_STREAM_H
#define THIN_PROVISIONING_FIXED_CHUNK_STREAM_H
#include "thin-provisioning/chunk_stream.h"
//----------------------------------------------------------------
namespace thin_provisioning {
class fixed_chunk_stream : public chunk_stream {
public:
fixed_chunk_stream(chunk_stream &stream, unsigned chunk_size);
~fixed_chunk_stream();
virtual bcache::block_address size() const;
virtual void rewind();
virtual bool next(bcache::block_address count = 1ull);
virtual bool eof() const;
virtual chunk const &get();
virtual void put(chunk const &c);
private:
bool next_big_chunk();
bool advance_one();
void put_big_chunk();
bcache::block_address index_;
chunk_stream &stream_;
unsigned chunk_size_;
chunk const *big_chunk_;
uint8_t *little_b_, *little_e_, *last_hashed_;
chunk little_chunk_;
};
}
//----------------------------------------------------------------
#endif

View File

@ -30,6 +30,7 @@
#include "persistent-data/space-maps/core.h" #include "persistent-data/space-maps/core.h"
#include "persistent-data/space-maps/disk.h" #include "persistent-data/space-maps/disk.h"
#include "thin-provisioning/cache_stream.h" #include "thin-provisioning/cache_stream.h"
#include "thin-provisioning/fixed_chunk_stream.h"
#include "thin-provisioning/pool_stream.h" #include "thin-provisioning/pool_stream.h"
#include "thin-provisioning/commands.h" #include "thin-provisioning/commands.h"
#include "thin-provisioning/device_tree.h" #include "thin-provisioning/device_tree.h"
@ -54,7 +55,6 @@ using namespace thin_provisioning;
namespace { namespace {
bool factor_of(block_address f, block_address n) { bool factor_of(block_address f, block_address n) {
cerr << n << " % " << f << "\n";
return (n % f) == 0; return (n % f) == 0;
} }
@ -145,6 +145,21 @@ namespace {
class duplicate_detector { class duplicate_detector {
public: public:
void scan_with_variable_sized_chunks(chunk_stream &stream) {
variable_chunk_stream vstream(stream, 4096);
scan(vstream);
}
void scan_with_fixed_sized_chunks(chunk_stream &stream, block_address chunk_size) {
fixed_chunk_stream fstream(stream, chunk_size);
scan(fstream);
}
duplicate_counter const &get_results() const {
return results_;
}
private:
void scan(chunk_stream &stream) { void scan(chunk_stream &stream) {
block_address total_seen(0); block_address total_seen(0);
auto_ptr<progress_monitor> pbar = create_progress_bar("Examining data"); auto_ptr<progress_monitor> pbar = create_progress_bar("Examining data");
@ -164,17 +179,6 @@ namespace {
results_.display_results(stream); results_.display_results(stream);
} }
void scan_with_variable_sized_chunks(chunk_stream &stream) {
variable_chunk_stream vstream(stream, 4096);
scan(vstream);
}
duplicate_counter const &get_results() const {
return results_;
}
private:
void examine(chunk const &c) { void examine(chunk const &c) {
if (all_zeroes(c)) if (all_zeroes(c))
results_.add_zero_duplicate(c.len_); results_.add_zero_duplicate(c.len_);
@ -230,8 +234,16 @@ namespace {
if (fs.content_based_chunks) if (fs.content_based_chunks)
detector.scan_with_variable_sized_chunks(pstream); detector.scan_with_variable_sized_chunks(pstream);
else else {
detector.scan(pstream); if (*fs.block_size) {
if (factor_of(*fs.block_size, block_size))
block_size = *fs.block_size;
else
throw runtime_error("specified block size is not a factor of the pool chunk size\n");
}
detector.scan_with_fixed_sized_chunks(pstream, block_size);
}
return 0; return 0;
} }
@ -254,7 +266,7 @@ namespace {
if (fs.content_based_chunks) if (fs.content_based_chunks)
dd.scan_with_variable_sized_chunks(stream); dd.scan_with_variable_sized_chunks(stream);
else else
dd.scan(stream); dd.scan_with_fixed_sized_chunks(stream, block_size);
return 0; return 0;
} }