From 664841ad03506ba1da2b44d9e23623e09f3f3285 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Tue, 8 Sep 2015 17:09:41 +0100 Subject: [PATCH] [thin_show_dups] Support fractions of a pool block size --- Makefile.in | 1 + thin-provisioning/fixed_chunk_stream.cc | 113 ++++++++++++++++++++++ thin-provisioning/fixed_chunk_stream.h | 39 ++++++++ thin-provisioning/thin_show_duplicates.cc | 42 +++++--- 4 files changed, 180 insertions(+), 15 deletions(-) create mode 100644 thin-provisioning/fixed_chunk_stream.cc create mode 100644 thin-provisioning/fixed_chunk_stream.h diff --git a/Makefile.in b/Makefile.in index d09c873..89d45fd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -75,6 +75,7 @@ SOURCE=\ thin-provisioning/cache_stream.cc \ thin-provisioning/chunk_stream.cc \ thin-provisioning/device_tree.cc \ + thin-provisioning/fixed_chunk_stream.cc \ thin-provisioning/human_readable_format.cc \ thin-provisioning/mapping_tree.cc \ thin-provisioning/metadata.cc \ diff --git a/thin-provisioning/fixed_chunk_stream.cc b/thin-provisioning/fixed_chunk_stream.cc new file mode 100644 index 0000000..ea031dd --- /dev/null +++ b/thin-provisioning/fixed_chunk_stream.cc @@ -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; +} + +//---------------------------------------------------------------- diff --git a/thin-provisioning/fixed_chunk_stream.h b/thin-provisioning/fixed_chunk_stream.h new file mode 100644 index 0000000..f17d15a --- /dev/null +++ b/thin-provisioning/fixed_chunk_stream.h @@ -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 diff --git a/thin-provisioning/thin_show_duplicates.cc b/thin-provisioning/thin_show_duplicates.cc index 3352760..89c0c9d 100644 --- a/thin-provisioning/thin_show_duplicates.cc +++ b/thin-provisioning/thin_show_duplicates.cc @@ -30,6 +30,7 @@ #include "persistent-data/space-maps/core.h" #include "persistent-data/space-maps/disk.h" #include "thin-provisioning/cache_stream.h" +#include "thin-provisioning/fixed_chunk_stream.h" #include "thin-provisioning/pool_stream.h" #include "thin-provisioning/commands.h" #include "thin-provisioning/device_tree.h" @@ -54,7 +55,6 @@ using namespace thin_provisioning; namespace { bool factor_of(block_address f, block_address n) { - cerr << n << " % " << f << "\n"; return (n % f) == 0; } @@ -145,6 +145,21 @@ namespace { class duplicate_detector { 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) { block_address total_seen(0); auto_ptr pbar = create_progress_bar("Examining data"); @@ -164,17 +179,6 @@ namespace { 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) { if (all_zeroes(c)) results_.add_zero_duplicate(c.len_); @@ -230,8 +234,16 @@ namespace { if (fs.content_based_chunks) detector.scan_with_variable_sized_chunks(pstream); - else - detector.scan(pstream); + else { + 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; } @@ -254,7 +266,7 @@ namespace { if (fs.content_based_chunks) dd.scan_with_variable_sized_chunks(stream); else - dd.scan(stream); + dd.scan_with_fixed_sized_chunks(stream, block_size); return 0; }