diff --git a/block.h b/block.h index 340a33c..7af2cdd 100644 --- a/block.h +++ b/block.h @@ -30,6 +30,7 @@ #include #include +#include //---------------------------------------------------------------- @@ -39,12 +40,47 @@ namespace persistent_data { typedef uint64_t block_address; - template + template + class buffer : private boost::noncopyable { + public: + unsigned char &operator[](unsigned index) { + if (index >= BlockSize) + throw std::runtime_error("buffer index out of bounds"); + + return data_[index]; + } + + unsigned char const &operator[](unsigned index) const { + if (index >= BlockSize) + throw std::runtime_error("buffer index out of bounds"); + + return data_[index]; + } + + unsigned char *raw() { + return data_; + } + + unsigned char const *raw() const { + return data_; + } + + static void *operator new(size_t s) { + return ::memalign(Alignment, s); + } + + static void operator delete(void *p) { + free(p); + } + + private: + unsigned char data_[BlockSize]; + }; + + template class block_io : private boost::noncopyable { public: typedef boost::shared_ptr ptr; - typedef unsigned char buffer[BlockSize]; - typedef unsigned char const const_buffer[BlockSize]; block_io(std::string const &path, block_address nr_blocks, bool writeable = false); ~block_io(); @@ -53,8 +89,8 @@ namespace persistent_data { return nr_blocks_; } - void read_buffer(block_address location, buffer &buf) const; - void write_buffer(block_address location, const_buffer &buf); + void read_buffer(block_address location, buffer &buf) const; + void write_buffer(block_address location, buffer const &buf); private: int fd_; @@ -72,23 +108,20 @@ namespace persistent_data { unsigned max_concurrent_locks, bool writeable = false); - typedef unsigned char buffer[BlockSize]; - typedef unsigned char const const_buffer[BlockSize]; - class validator { public: typedef boost::shared_ptr ptr; virtual ~validator() {} - virtual void check(const_buffer &b, block_address location) const = 0; - virtual void prepare(buffer &b, block_address location) const = 0; + virtual void check(buffer const &b, block_address location) const = 0; + virtual void prepare(buffer &b, block_address location) const = 0; }; class noop_validator : public validator { public: - void check(const_buffer &b, block_address location) const {} - void prepare(buffer &b, block_address location) const {} + void check(buffer const &b, block_address location) const {} + void prepare(buffer &b, block_address location) const {} }; enum block_type { @@ -96,7 +129,7 @@ namespace persistent_data { BT_NORMAL }; - struct block { + struct block : private boost::noncopyable { typedef boost::shared_ptr ptr; block(typename block_io::ptr io, @@ -118,12 +151,12 @@ namespace persistent_data { typename block_io::ptr io_; block_address location_; - buffer data_; + std::auto_ptr > data_; typename validator::ptr validator_; block_type bt_; bool dirty_; }; - typedef typename block::ptr block_ptr; + typedef typename block::ptr block_ptr; // FIXME: remove class read_ref { public: @@ -135,7 +168,7 @@ namespace persistent_data { read_ref const &operator =(read_ref const &rhs); block_address get_location() const; - const_buffer &data() const; + buffer const &data() const; protected: block_manager const &bm_; @@ -151,7 +184,7 @@ namespace persistent_data { typename block::ptr b); using read_ref::data; - buffer &data(); + buffer &data(); }; // Locking methods diff --git a/block.tcc b/block.tcc index c3a1210..0d48942 100644 --- a/block.tcc +++ b/block.tcc @@ -40,7 +40,7 @@ block_io::block_io(std::string const &path, block_address nr_blocks, writeable_(writeable) { // fd_ = ::open(path.c_str(), writeable ? (O_RDWR | O_CREAT) : O_RDONLY, 0666); - fd_ = ::open(path.c_str(), writeable ? O_RDWR : O_RDONLY, 0666); + fd_ = ::open(path.c_str(), O_DIRECT | O_SYNC | (writeable ? O_RDWR : O_RDONLY), 0666); if (fd_ < 0) throw std::runtime_error("couldn't open file"); } @@ -53,7 +53,7 @@ block_io::~block_io() template void -block_io::read_buffer(block_address location, buffer &buffer) const +block_io::read_buffer(block_address location, buffer &buffer) const { off_t r; r = ::lseek(fd_, BlockSize * location, SEEK_SET); @@ -62,7 +62,7 @@ block_io::read_buffer(block_address location, buffer &buffer) const ssize_t n; size_t remaining = BlockSize; - unsigned char *buf = buffer; + unsigned char *buf = buffer.raw(); do { n = ::read(fd_, buf, remaining); if (n > 0) { @@ -77,7 +77,7 @@ block_io::read_buffer(block_address location, buffer &buffer) const template void -block_io::write_buffer(block_address location, const_buffer &buffer) +block_io::write_buffer(block_address location, buffer const &buffer) { off_t r; r = ::lseek(fd_, BlockSize * location, SEEK_SET); @@ -86,7 +86,7 @@ block_io::write_buffer(block_address location, const_buffer &buffer) ssize_t n; size_t remaining = BlockSize; - unsigned char const *buf = buffer; + unsigned char const *buf = buffer.raw(); do { n = ::write(fd_, buf, remaining); if (n > 0) { @@ -118,16 +118,17 @@ block_manager::block::block(typename block_io::ptr io, bool zero) : io_(io), location_(location), + data_(new buffer()), validator_(v), bt_(bt), dirty_(false) { if (zero) { - memset(&data_, 0, sizeof(data_)); + memset(data_->raw(), 0, BlockSize); dirty_ = true; } else { - io_->read_buffer(location_, data_); - validator_->check(data_, location_); + io_->read_buffer(location_, *data_); + validator_->check(*data_, location_); } } @@ -142,8 +143,8 @@ void block_manager::block::flush() { if (dirty_) { - validator_->prepare(data_, location_); - io_->write_buffer(location_, data_); + validator_->prepare(*data_, location_); + io_->write_buffer(location_, *data_); } } @@ -203,10 +204,10 @@ block_manager::read_ref::get_location() const } template -typename block_manager::const_buffer & +buffer const & block_manager::read_ref::data() const { - return block_->data_; + return *block_->data_; } //-------------------------------- @@ -220,10 +221,10 @@ block_manager::write_ref::write_ref(block_manager const &b } template -typename block_manager::buffer & +buffer & block_manager::write_ref::data() { - return read_ref::block_->data_; + return *read_ref::block_->data_; } //---------------------------------------------------------------- @@ -285,7 +286,7 @@ block_manager::write_lock_zero(block_address location, boost::optional cached_block = cache_.get(location); if (cached_block) { (*cached_block)->check_write_lockable(); - memset(&(*cached_block)->data_, 0, BlockSize); + memset((*cached_block)->data_->raw(), 0, BlockSize); return write_ref(*this, *cached_block); } @@ -326,7 +327,7 @@ block_manager::superblock_zero(block_address location, if (cached_block) { (*cached_block)->check_write_lockable(); - memset(&(*cached_block)->data_, 0, BlockSize); + memset((*cached_block)->data_->raw(), 0, BlockSize); // FIXME: add a zero method to buffer (*cached_block)->validator_ = v; return write_ref(*this, *cached_block); } diff --git a/btree.h b/btree.h index 222322a..b87e6a6 100644 --- a/btree.h +++ b/btree.h @@ -176,7 +176,7 @@ namespace persistent_data { return node_ref( b.get_location(), reinterpret_cast( - const_cast(b.data()))); + const_cast(b.data().raw()))); } template @@ -186,7 +186,7 @@ namespace persistent_data { return node_ref( b.get_location(), reinterpret_cast( - const_cast(b.data()))); + const_cast(b.data().raw()))); } class ro_spine : private noncopyable { diff --git a/btree.tcc b/btree.tcc index fa16243..eb0584b 100644 --- a/btree.tcc +++ b/btree.tcc @@ -33,7 +33,7 @@ using namespace std; namespace { struct btree_node_validator : public block_manager<>::validator { - virtual void check(block_manager<>::const_buffer &b, block_address location) const { + virtual void check(buffer<> const &b, block_address location) const { disk_node const *data = reinterpret_cast(&b); node_header const *n = &data->header; crc32c sum(BTREE_CSUM_XOR); @@ -45,7 +45,7 @@ namespace { throw checksum_error("bad block nr in btree node"); } - virtual void prepare(block_manager<>::buffer &b, block_address location) const { + virtual void prepare(buffer<> &b, block_address location) const { disk_node *data = reinterpret_cast(&b); node_header *n = &data->header; n->blocknr = to_disk(location); diff --git a/metadata.cc b/metadata.cc index 0f49047..2253d8b 100644 --- a/metadata.cc +++ b/metadata.cc @@ -40,7 +40,7 @@ namespace { uint32_t const SUPERBLOCK_CSUM_SEED = 160774; struct superblock_validator : public block_manager<>::validator { - virtual void check(block_manager<>::const_buffer &b, block_address location) const { + virtual void check(buffer<> const &b, block_address location) const { superblock_disk const *sbd = reinterpret_cast(&b); crc32c sum(SUPERBLOCK_CSUM_SEED); sum.append(&sbd->flags_, MD_BLOCK_SIZE - sizeof(uint32_t)); @@ -48,7 +48,7 @@ namespace { throw checksum_error("bad checksum in superblock"); } - virtual void prepare(block_manager<>::buffer &b, block_address location) const { + virtual void prepare(buffer<> &b, block_address location) const { superblock_disk *sbd = reinterpret_cast(&b); crc32c sum(SUPERBLOCK_CSUM_SEED); sum.append(&sbd->flags_, MD_BLOCK_SIZE - sizeof(uint32_t)); @@ -127,6 +127,10 @@ metadata::metadata(std::string const &dev_path, open_type ot, case OPEN: tm_ = open_tm(dev_path, false); sb_ = read_superblock(tm_->get_bm()); + + if (sb_.version_ != 1) + throw runtime_error("unknown metadata version"); + metadata_sm_ = open_metadata_sm(tm_, &sb_.metadata_space_map_root_); tm_->set_sm(metadata_sm_); @@ -161,10 +165,10 @@ metadata::metadata(std::string const &dev_path, open_type ot, } } -metadata::metadata(std::string const &dev_path, block_address held_root) +metadata::metadata(std::string const &dev_path, block_address metadata_snap) { tm_ = open_tm(dev_path, false); - sb_ = read_superblock(tm_->get_bm(), held_root); + sb_ = read_superblock(tm_->get_bm(), metadata_snap); // We don't open the metadata sm for a held root //metadata_sm_ = open_metadata_sm(tm_, &sb_.metadata_space_map_root_); tm_->set_sm(metadata_sm_); @@ -208,7 +212,7 @@ metadata::commit() superblock_validator v; write_ref superblock = tm_->get_bm()->superblock_zero(SUPERBLOCK_LOCATION, mk_validator(new superblock_validator())); - superblock_disk *disk = reinterpret_cast(superblock.data()); + superblock_disk *disk = reinterpret_cast(superblock.data().raw()); superblock_traits::pack(sb_, *disk); } diff --git a/metadata.h b/metadata.h index 2317027..12f9f0c 100644 --- a/metadata.h +++ b/metadata.h @@ -151,7 +151,7 @@ namespace thin_provisioning { sector_t data_block_size = 128, block_address nr_data_blocks = 0); // Only used if CREATE - metadata(std::string const &dev_path, block_address held_root); + metadata(std::string const &dev_path, block_address metadata_snap); void commit(); diff --git a/metadata_checker.cc b/metadata_checker.cc index 417a59b..3d96e0e 100644 --- a/metadata_checker.cc +++ b/metadata_checker.cc @@ -171,11 +171,11 @@ thin_provisioning::metadata_check(metadata::ptr md) block_counter metadata_counter, data_counter; - if (md->sb_.held_root_) { + if (md->sb_.metadata_snap_) { block_manager<>::ptr bm = md->tm_->get_bm(); - block_address root = md->sb_.held_root_; + block_address root = md->sb_.metadata_snap_; metadata_counter.inc(root); diff --git a/metadata_disk_structures.cc b/metadata_disk_structures.cc index 8a0fe41..bfe3a97 100644 --- a/metadata_disk_structures.cc +++ b/metadata_disk_structures.cc @@ -55,7 +55,7 @@ superblock_traits::unpack(superblock_disk const &disk, superblock &value) value.time_ = to_cpu(disk.time_); value.trans_id_ = to_cpu(disk.trans_id_); - value.held_root_ = to_cpu(disk.held_root_); + value.metadata_snap_ = to_cpu(disk.metadata_snap_); ::memcpy(value.data_space_map_root_, disk.data_space_map_root_, @@ -88,7 +88,7 @@ superblock_traits::pack(superblock const &value, superblock_disk &disk) disk.time_ = to_disk<__le32>(value.time_); disk.trans_id_ = to_disk<__le64>(value.trans_id_); - disk.held_root_ = to_disk<__le64>(value.held_root_); + disk.metadata_snap_ = to_disk<__le64>(value.metadata_snap_); ::memcpy(disk.data_space_map_root_, value.data_space_map_root_, diff --git a/metadata_disk_structures.h b/metadata_disk_structures.h index 74c2209..e7cf130 100644 --- a/metadata_disk_structures.h +++ b/metadata_disk_structures.h @@ -66,7 +66,7 @@ namespace thin_provisioning { __le64 trans_id_; /* root for userspace's transaction (for migration and friends) */ - __le64 held_root_; + __le64 metadata_snap_; __u8 data_space_map_root_[SPACE_MAP_ROOT_SIZE]; __u8 metadata_space_map_root_[SPACE_MAP_ROOT_SIZE]; @@ -99,7 +99,7 @@ namespace thin_provisioning { uint64_t trans_id_; /* root for userspace's transaction (for migration and friends) */ - uint64_t held_root_; + uint64_t metadata_snap_; unsigned char data_space_map_root_[SPACE_MAP_ROOT_SIZE]; unsigned char metadata_space_map_root_[SPACE_MAP_ROOT_SIZE]; diff --git a/metadata_dumper.cc b/metadata_dumper.cc index 4a3656f..c442b6d 100644 --- a/metadata_dumper.cc +++ b/metadata_dumper.cc @@ -186,10 +186,15 @@ namespace { void thin_provisioning::metadata_dump(metadata::ptr md, emitter::ptr e, bool repair) { + optional md_snap = md->sb_.metadata_snap_ ? + optional(md->sb_.metadata_snap_) : + optional(); + e->begin_superblock("", md->sb_.time_, md->sb_.trans_id_, md->sb_.data_block_size_, - md->data_sm_->get_nr_blocks()); + md->data_sm_->get_nr_blocks(), + md_snap); details_extractor::ptr de(new details_extractor); diff --git a/space_map_disk.cc b/space_map_disk.cc index 4c7a7ed..2555cab 100644 --- a/space_map_disk.cc +++ b/space_map_disk.cc @@ -38,7 +38,7 @@ namespace { uint64_t const BITMAP_CSUM_XOR = 240779; struct bitmap_block_validator : public block_manager<>::validator { - virtual void check(block_manager<>::const_buffer &b, block_address location) const { + virtual void check(buffer<> const &b, block_address location) const { bitmap_header const *data = reinterpret_cast(&b); crc32c sum(BITMAP_CSUM_XOR); sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t)); @@ -49,7 +49,7 @@ namespace { throw checksum_error("bad block nr in space map bitmap"); } - virtual void prepare(block_manager<>::buffer &b, block_address location) const { + virtual void prepare(buffer<> &b, block_address location) const { bitmap_header *data = reinterpret_cast(&b); data->blocknr = to_disk(location); @@ -70,7 +70,7 @@ namespace { // FIXME: factor out the common code in these validators struct index_block_validator : public block_manager<>::validator { - virtual void check(block_manager<>::const_buffer &b, block_address location) const { + virtual void check(buffer<> const &b, block_address location) const { metadata_index const *mi = reinterpret_cast(&b); crc32c sum(INDEX_CSUM_XOR); sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t)); @@ -81,7 +81,7 @@ namespace { throw checksum_error("bad block nr in metadata index block"); } - virtual void prepare(block_manager<>::buffer &b, block_address location) const { + virtual void prepare(buffer<> &b, block_address location) const { metadata_index *mi = reinterpret_cast(&b); mi->blocknr_ = to_disk(location); diff --git a/thin_debug.cc b/thin_debug.cc index 45a3d73..0e5abdd 100644 --- a/thin_debug.cc +++ b/thin_debug.cc @@ -193,7 +193,7 @@ namespace { field(f, "version", sb.version_); field(f, "time", sb.time_); field(f, "trans id", sb.trans_id_); - field(f, "held root", sb.held_root_); + field(f, "metadata snap", sb.metadata_snap_); field(f, "data mapping root", sb.data_mapping_root_); field(f, "device details root", sb.device_details_root_); field(f, "data block size", sb.data_block_size_); diff --git a/transaction_manager.cc b/transaction_manager.cc index 5960e7d..ad9e26b 100644 --- a/transaction_manager.cc +++ b/transaction_manager.cc @@ -73,7 +73,7 @@ transaction_manager::shadow(block_address orig, validator v) throw runtime_error("couldn't allocate new block"); write_ref dest = bm_->write_lock_zero(*mb, v); - ::memcpy(dest.data(), src.data(), MD_BLOCK_SIZE); + ::memcpy(dest.data().raw(), src.data().raw(), MD_BLOCK_SIZE); // FIXME: use buffer copy method ref_t count = sm_->get_count(orig); if (count == 0)