Merge branch 'master' into v0.7-devel

Conflicts:
	persistent-data/file_utils.cc
	persistent-data/file_utils.h
This commit is contained in:
Joe Thornber 2016-04-05 13:13:10 +01:00
commit 3c02151a4f
6 changed files with 49 additions and 30 deletions

View File

@ -4,6 +4,7 @@ v0.6.2
- Fix bug in thin_delta - Fix bug in thin_delta
- Fix recent regression in thin_repair. - Fix recent regression in thin_repair.
- Force g++-98 dialect - Force g++-98 dialect
- Fix bug in thin_trim
v0.6.1 v0.6.1
====== ======

View File

@ -8,6 +8,8 @@
#include <unistd.h> #include <unistd.h>
using namespace base; using namespace base;
using namespace bcache;
using namespace persistent_data;
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -25,7 +27,7 @@ persistent_data::get_nr_blocks(string const &path, sector_t block_size)
strerror(errno)); strerror(errno));
if (S_ISREG(info.st_mode) && info.st_size) if (S_ISREG(info.st_mode) && info.st_size)
nr_blocks = div_up<block_address>(info.st_size, block_size); nr_blocks = div_down<block_address>(info.st_size, block_size);
else if (S_ISBLK(info.st_mode)) { else if (S_ISBLK(info.st_mode)) {
// To get the size of a block device we need to // To get the size of a block device we need to
@ -48,10 +50,16 @@ persistent_data::get_nr_blocks(string const &path, sector_t block_size)
return nr_blocks; return nr_blocks;
} }
block_address
persistent_data::get_nr_metadata_blocks(string const &path)
{
return get_nr_blocks(path, MD_BLOCK_SIZE);
}
persistent_data::block_manager<>::ptr persistent_data::block_manager<>::ptr
persistent_data::open_bm(std::string const &dev_path, block_manager<>::mode m, bool excl) persistent_data::open_bm(std::string const &dev_path, block_manager<>::mode m, bool excl)
{ {
block_address nr_blocks = get_nr_blocks(dev_path); block_address nr_blocks = get_nr_metadata_blocks(dev_path);
return block_manager<>::ptr(new block_manager<>(dev_path, nr_blocks, 1, m, excl)); return block_manager<>::ptr(new block_manager<>(dev_path, nr_blocks, 1, m, excl));
} }

View File

@ -10,6 +10,8 @@
// FIXME: move to a different unit // FIXME: move to a different unit
namespace persistent_data { namespace persistent_data {
persistent_data::block_address get_nr_blocks(string const &path, sector_t block_size = MD_BLOCK_SIZE); persistent_data::block_address get_nr_blocks(string const &path, sector_t block_size = MD_BLOCK_SIZE);
block_address get_nr_metadata_blocks(string const &path);
block_manager<>::ptr open_bm(std::string const &dev_path, block_manager<>::ptr open_bm(std::string const &dev_path,
block_manager<>::mode m, bool excl = true); block_manager<>::mode m, bool excl = true);

View File

@ -44,7 +44,7 @@ using namespace thin_provisioning;
namespace { namespace {
block_manager<>::ptr block_manager<>::ptr
open_bm(string const &path) { open_bm(string const &path) {
block_address nr_blocks = get_nr_blocks(path); block_address nr_blocks = get_nr_metadata_blocks(path);
block_manager<>::mode m = block_manager<>::READ_ONLY; block_manager<>::mode m = block_manager<>::READ_ONLY;
return block_manager<>::ptr(new block_manager<>(path, nr_blocks, 1, m)); return block_manager<>::ptr(new block_manager<>(path, nr_blocks, 1, m));
} }

View File

@ -23,7 +23,7 @@ using namespace thin_provisioning;
namespace { namespace {
block_manager<>::ptr block_manager<>::ptr
open_bm(string const &path) { open_bm(string const &path) {
block_address nr_blocks = get_nr_blocks(path); block_address nr_blocks = get_nr_metadata_blocks(path);
block_manager<>::mode m = block_manager<>::READ_ONLY; block_manager<>::mode m = block_manager<>::READ_ONLY;
return block_manager<>::ptr(new block_manager<>(path, nr_blocks, 1, m)); return block_manager<>::ptr(new block_manager<>(path, nr_blocks, 1, m));
} }

View File

@ -22,17 +22,6 @@ using namespace thin_provisioning;
//---------------------------------------------------------------- //----------------------------------------------------------------
namespace { namespace {
void confirm_pool_is_not_active() {
cout << "The pool must *not* be active when running this tool.\n"
<< "Do you wish to continue? [Y/N]\n"
<< endl;
string input;
cin >> input;
if (input != "Y")
exit(0);
}
class discard_emitter { class discard_emitter {
public: public:
discard_emitter(string const &data_dev, unsigned block_size, uint64_t nr_blocks) discard_emitter(string const &data_dev, unsigned block_size, uint64_t nr_blocks)
@ -50,6 +39,8 @@ namespace {
range[0] = block_to_byte(b); range[0] = block_to_byte(b);
range[1] = block_to_byte(e) - range[0]; range[1] = block_to_byte(e) - range[0];
cerr << "emitting discard for blocks (" << b << ", " << e << "]\n";
if (ioctl(fd_, BLKDISCARD, &range)) if (ioctl(fd_, BLKDISCARD, &range))
throw runtime_error("discard ioctl failed"); throw runtime_error("discard ioctl failed");
} }
@ -98,43 +89,57 @@ namespace {
unsigned block_size_; unsigned block_size_;
}; };
class trim_visitor : public space_map_detail::visitor { class trim_iterator : public space_map::iterator {
public: public:
trim_visitor(discard_emitter &e) trim_iterator(discard_emitter &e)
: emitter_(e) { : emitter_(e) {
} }
virtual void visit(space_map_detail::missing_counts const &mc) { virtual void operator() (block_address b, ref_t count) {
throw std::runtime_error("corrupt metadata, please use thin_check for details"); highest_ = b;
if (count) {
if (last_referenced_ && (b > *last_referenced_ + 1))
emitter_.emit(*last_referenced_ + 1, b);
last_referenced_ = b;
}
} }
virtual void visit(block_address b, uint32_t count) { void complete() {
if (last_visited_ && (b > *last_visited_ + 1)) if (last_referenced_) {
emitter_.emit(*last_visited_ + 1, b); if (*last_referenced_ != *highest_)
emitter_.emit(*last_referenced_, *highest_ + 1ull);
last_visited_ = b; } else if (highest_)
emitter_.emit(0ull, *highest_ + 1);
} }
private: private:
discard_emitter &emitter_; discard_emitter &emitter_;
boost::optional<block_address> last_visited_; boost::optional<block_address> last_referenced_;
boost::optional<block_address> highest_;
}; };
int trim(string const &metadata_dev, string const &data_dev) { int trim(string const &metadata_dev, string const &data_dev) {
cerr << "in trim\n";
// We can trim any block that has zero count in the data // We can trim any block that has zero count in the data
// space map. // space map.
block_manager<>::ptr bm = open_bm(metadata_dev, block_manager<>::READ_ONLY); block_manager<>::ptr bm = open_bm(metadata_dev, block_manager<>::READ_ONLY);
metadata md(bm); metadata md(bm);
if (!md.data_sm_->get_nr_free()) if (!md.data_sm_->get_nr_free()) {
cerr << "All data blocks allocated, nothing to discard\n";
return 0; return 0;
}
discard_emitter de(data_dev, md.sb_.data_block_size_, discard_emitter de(data_dev, md.sb_.data_block_size_,
md.data_sm_->get_nr_blocks()); md.data_sm_->get_nr_blocks());
trim_visitor tv(de); trim_iterator ti(de);
confirm_pool_is_not_active(); md.data_sm_->iterate(ti);
md.data_sm_->visit(tv); ti.complete();
return 0; return 0;
} }
@ -155,9 +160,8 @@ thin_trim_cmd::thin_trim_cmd()
void void
thin_trim_cmd::usage(std::ostream &out) const thin_trim_cmd::usage(std::ostream &out) const
{ {
out << "Usage: " << get_name() << " [options] {device|file}\n" out << "Usage: " << get_name() << " [options] --metadata-dev {device|file} --data-dev {device|file}\n"
<< "Options:\n" << "Options:\n"
<< " {--pool-inactive}\n"
<< " {-h|--help}\n" << " {-h|--help}\n"
<< " {-V|--version}" << endl; << " {-V|--version}" << endl;
} }
@ -188,6 +192,10 @@ thin_trim_cmd::run(int argc, char **argv)
fs.data_dev = optarg; fs.data_dev = optarg;
break; break;
case 2:
cerr << "--pool-inactive no longer required since we ensure the metadata device is opened exclusively.\n";
break;
case 'h': case 'h':
usage(cout); usage(cout);
return 0; return 0;