diff --git a/persistent-data/block.h b/persistent-data/block.h index fa587ac..09646c7 100644 --- a/persistent-data/block.h +++ b/persistent-data/block.h @@ -52,7 +52,8 @@ namespace persistent_data { block_manager(std::string const &path, block_address nr_blocks, unsigned max_concurrent_locks, - mode m); + mode m, + bool excl = true); class read_ref { public: @@ -134,7 +135,8 @@ namespace persistent_data { bool is_locked(block_address b) const; private: - int open_or_create_block_file(std::string const &path, off_t file_size, mode m); + int open_or_create_block_file(std::string const &path, off_t file_size, + mode m, bool excl); void check(block_address b) const; int fd_; diff --git a/persistent-data/block.tcc b/persistent-data/block.tcc index 529f7af..d21caad 100644 --- a/persistent-data/block.tcc +++ b/persistent-data/block.tcc @@ -80,7 +80,7 @@ namespace { throw runtime_error(out.str()); } - int fd = open_file(path, O_CREAT | O_RDWR); + int fd = open_file(path, O_CREAT | O_EXCL | O_RDWR); int r = ::ftruncate(fd, file_size); if (r < 0) @@ -89,14 +89,18 @@ namespace { return fd; } - int open_block_file(string const &path, off_t min_size, bool writeable) { + int open_block_file(string const &path, off_t min_size, bool writeable, bool excl = true) { if (!file_exists(path)) { ostringstream out; out << __FUNCTION__ << ": file '" << path << "' doesn't exist"; throw runtime_error(out.str()); } - return open_file(path, writeable ? O_RDWR : O_RDONLY); + int flags = writeable ? O_RDWR : O_RDONLY; + if (excl) + flags |= O_EXCL; + + return open_file(path, flags); } }; @@ -208,8 +212,9 @@ namespace persistent_data { block_manager::block_manager(std::string const &path, block_address nr_blocks, unsigned max_concurrent_blocks, - mode m) - : fd_(open_or_create_block_file(path, nr_blocks * BlockSize, m)), + mode m, + bool excl) + : fd_(open_or_create_block_file(path, nr_blocks * BlockSize, m, excl)), bc_(fd_, BlockSize >> SECTOR_SHIFT, nr_blocks, 1024u * 1024u * 16), superblock_ref_count_(0) { @@ -217,14 +222,14 @@ namespace persistent_data { template int - block_manager::open_or_create_block_file(string const &path, off_t file_size, mode m) + block_manager::open_or_create_block_file(string const &path, off_t file_size, mode m, bool excl) { switch (m) { case READ_ONLY: - return open_block_file(path, file_size, false); + return open_block_file(path, file_size, false, excl); case READ_WRITE: - return open_block_file(path, file_size, true); + return open_block_file(path, file_size, true, excl); case CREATE: return create_block_file(path, file_size); diff --git a/persistent-data/file_utils.cc b/persistent-data/file_utils.cc index 3dc9e2d..2467079 100644 --- a/persistent-data/file_utils.cc +++ b/persistent-data/file_utils.cc @@ -48,10 +48,10 @@ persistent_data::get_nr_blocks(string const &path) } persistent_data::block_manager<>::ptr -persistent_data::open_bm(std::string const &dev_path, block_manager<>::mode m) +persistent_data::open_bm(std::string const &dev_path, block_manager<>::mode m, bool excl) { block_address nr_blocks = get_nr_blocks(dev_path); - return block_manager<>::ptr(new block_manager<>(dev_path, nr_blocks, 1, m)); + return block_manager<>::ptr(new block_manager<>(dev_path, nr_blocks, 1, m, excl)); } void diff --git a/persistent-data/file_utils.h b/persistent-data/file_utils.h index d08fa96..fcf203d 100644 --- a/persistent-data/file_utils.h +++ b/persistent-data/file_utils.h @@ -10,7 +10,8 @@ // FIXME: move to a different unit namespace persistent_data { persistent_data::block_address get_nr_blocks(string const &path); - block_manager<>::ptr open_bm(std::string const &dev_path, block_manager<>::mode m); + block_manager<>::ptr open_bm(std::string const &dev_path, + block_manager<>::mode m, bool excl = true); void check_file_exists(std::string const &file); } diff --git a/thin-provisioning/metadata.cc b/thin-provisioning/metadata.cc index 098314c..aa29f78 100644 --- a/thin-provisioning/metadata.cc +++ b/thin-provisioning/metadata.cc @@ -118,7 +118,7 @@ metadata::metadata(std::string const &dev_path, open_type ot, metadata::metadata(std::string const &dev_path, block_address metadata_snap) { - tm_ = open_tm(open_bm(dev_path, block_manager<>::READ_ONLY)); + tm_ = open_tm(open_bm(dev_path, block_manager<>::READ_ONLY, !metadata_snap)); sb_ = read_superblock(tm_->get_bm(), metadata_snap); // We don't open the metadata sm for a held root diff --git a/thin-provisioning/thin_dump.cc b/thin-provisioning/thin_dump.cc index 853a512..c302bd0 100644 --- a/thin-provisioning/thin_dump.cc +++ b/thin-provisioning/thin_dump.cc @@ -27,6 +27,7 @@ #include "xml_format.h" #include "version.h" #include "thin-provisioning/commands.h" +#include "persistent-data/file_utils.h" using namespace persistent_data; using namespace std; @@ -38,24 +39,25 @@ struct flags { }; namespace { + block_address find_metadata_snap(string const &path) + { + superblock_detail::superblock sb = read_superblock(open_bm(path, block_manager<>::READ_ONLY, false), 0); + uint64_t ms = sb.metadata_snap_; + + if (!ms) { + cerr << "no metadata snapshot found!" << endl; + exit(1); + } + + return ms; + } + int dump_(string const &path, ostream &out, string const &format, struct flags &flags, block_address metadata_snap) { try { metadata::ptr md(new metadata(path, metadata_snap)); emitter::ptr e; - if (flags.find_metadata_snap) { - uint64_t metadata_snap_root = md->sb_.metadata_snap_; /* FIXME: use thin_pool method? */ - - if (metadata_snap_root) { - md.reset(); - md = metadata::ptr(new metadata(path, metadata_snap_root)); - } else { - cerr << "no metadata snapshot found!" << endl; - exit(1); - } - } - if (format == "xml") e = create_xml_emitter(out); else if (format == "human_readable") @@ -164,6 +166,9 @@ int thin_dump_main(int argc, char **argv) return 1; } + if (flags.find_metadata_snap) + metadata_snap = find_metadata_snap(argv[optind]); + return dump(argv[optind], output, format, flags, metadata_snap); }