[thin_show_dups] Support fractions of a pool block size
This commit is contained 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 \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								thin-provisioning/fixed_chunk_stream.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								thin-provisioning/fixed_chunk_stream.cc
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										39
									
								
								thin-provisioning/fixed_chunk_stream.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								thin-provisioning/fixed_chunk_stream.h
									
									
									
									
									
										Normal 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
 | 
			
		||||
@@ -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<progress_monitor> 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 {
 | 
			
		||||
			if (*fs.block_size) {
 | 
			
		||||
				if (factor_of(*fs.block_size, block_size))
 | 
			
		||||
					block_size = *fs.block_size;
 | 
			
		||||
				else
 | 
			
		||||
			detector.scan(pstream);
 | 
			
		||||
					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;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user