From 7f7ba950efe7abb66d2f1450ec823f17c341e10a Mon Sep 17 00:00:00 2001 From: Ming-Hung Tsai Date: Sun, 31 May 2020 20:14:42 +0800 Subject: [PATCH] [thin_pool] Complete device creation - Set up the device details - Cache device details of opened devices - Update changed devices at once while committing the pool --- thin-provisioning/thin_pool.cc | 131 +++++++++++++++++++++++++-------- thin-provisioning/thin_pool.h | 14 ++++ 2 files changed, 114 insertions(+), 31 deletions(-) diff --git a/thin-provisioning/thin_pool.cc b/thin-provisioning/thin_pool.cc index 1436b4b..09658db 100644 --- a/thin-provisioning/thin_pool.cc +++ b/thin-provisioning/thin_pool.cc @@ -33,7 +33,20 @@ using namespace thin_provisioning; thin::thin(thin_dev_t dev, thin_pool &pool) : dev_(dev), - pool_(pool) + pool_(pool), + details_(pool.get_transaction_id(), pool.get_time()), + open_count_(1), + changed_(true) +{ +} + +thin::thin(thin_dev_t dev, thin_pool &pool, + device_tree_detail::device_details const &details) + : dev_(dev), + pool_(pool), + details_(details), + open_count_(1), + changed_(false) { } @@ -54,6 +67,10 @@ bool thin::insert(block_address thin_block, block_address data_block) { uint64_t key[2] = {dev_, thin_block}; + + ++details_.mapped_blocks_; + changed_ = true; + mapping_tree_detail::block_time bt; bt.block_ = data_block; bt.time_ = 0; // FIXME: use current time. @@ -65,41 +82,29 @@ thin::remove(block_address thin_block) { uint64_t key[2] = {dev_, thin_block}; pool_.md_->mappings_->remove(key); + + --details_.mapped_blocks_; + changed_ = true; } void thin::set_snapshot_time(uint32_t time) { - uint64_t key[1] = { dev_ }; - boost::optional mdetail = pool_.md_->details_->lookup(key); - if (!mdetail) - throw runtime_error("no such device"); - - mdetail->snapshotted_time_ = time; - pool_.md_->details_->insert(key, *mdetail); + details_.snapshotted_time_ = time; + changed_ = true; } block_address thin::get_mapped_blocks() const { - uint64_t key[1] = { dev_ }; - boost::optional mdetail = pool_.md_->details_->lookup(key); - if (!mdetail) - throw runtime_error("no such device"); - - return mdetail->mapped_blocks_; + return details_.mapped_blocks_; } void thin::set_mapped_blocks(block_address count) { - uint64_t key[1] = { dev_ }; - boost::optional mdetail = pool_.md_->details_->lookup(key); - if (!mdetail) - throw runtime_error("no such device"); - - mdetail->mapped_blocks_ = count; - pool_.md_->details_->insert(key, *mdetail); + details_.mapped_blocks_ = count; + changed_ = true; } //-------------------------------- @@ -131,14 +136,15 @@ thin_pool::create_thin(thin_dev_t dev) uint64_t key[1] = {dev}; if (device_exists(dev)) - throw std::runtime_error("Device already exists"); + throw std::runtime_error("device already exists"); single_mapping_tree::ptr new_tree(new single_mapping_tree(*md_->tm_, mapping_tree_detail::block_time_ref_counter(md_->data_sm_))); md_->mappings_top_level_->insert(key, new_tree->get_root()); md_->mappings_->set_root(md_->mappings_top_level_->get_root()); // FIXME: ugly - // FIXME: doesn't set up the device details + thin::ptr r = create_device(dev); + close_device(r); } void @@ -174,6 +180,13 @@ thin_pool::del(thin_dev_t dev) md_->mappings_top_level_->remove(key); } +void +thin_pool::commit() +{ + write_changed_details(); + md_->commit(); +} + void thin_pool::set_transaction_id(uint64_t id) { @@ -226,17 +239,16 @@ thin_pool::get_data_dev_size() const return md_->data_sm_->get_nr_blocks(); } +uint32_t +thin_pool::get_time() const +{ + return md_->sb_.time_; +} + thin::ptr thin_pool::open_thin(thin_dev_t dev) { - uint64_t key[1] = {dev}; - boost::optional mdetails = md_->details_->lookup(key); - if (!mdetails) - throw runtime_error("no such device"); - - thin *ptr = new thin(dev, *this); - thin::ptr r(ptr); - return r; + return open_device(dev); } bool @@ -246,4 +258,61 @@ thin_pool::device_exists(thin_dev_t dev) const return !!md_->details_->lookup(key); } +thin::ptr +thin_pool::create_device(thin_dev_t dev) +{ + device_map::iterator it = thin_devices_.find(dev); + if (it != thin_devices_.end()) + throw std::runtime_error("device already exists"); + + thin::ptr td(new thin(dev, *this)); + thin_devices_[dev] = td; + return td; +} + +thin::ptr +thin_pool::open_device(thin_dev_t dev) +{ + device_map::iterator it = thin_devices_.find(dev); + if (it != thin_devices_.end()) { + thin::ptr td = it->second; + td->open_count_++; + return td; + } + + uint64_t key[1] = {dev}; + device_tree::maybe_value details = md_->details_->lookup(key); + if (!details) + throw std::runtime_error("no such device"); + + thin::ptr td(new thin(dev, *this, *details)); + thin_devices_[dev] = td; + return td; +} + +void +thin_pool::close_device(thin::ptr td) +{ + td->open_count_--; +} + +void +thin_pool::write_changed_details() +{ + for (auto it = thin_devices_.cbegin(); it != thin_devices_.cend(); ) { + uint64_t key[1] = {it->first}; + thin::ptr td = it->second; + + if (td->changed_) { + md_->details_->insert(key, td->details_); + td->changed_ = false; + } + + if (!td->open_count_) + it = thin_devices_.erase(it); + else + ++it; + } +} + //---------------------------------------------------------------- diff --git a/thin-provisioning/thin_pool.h b/thin-provisioning/thin_pool.h index abbb47b..6874e61 100644 --- a/thin-provisioning/thin_pool.h +++ b/thin-provisioning/thin_pool.h @@ -49,9 +49,14 @@ namespace thin_provisioning { private: friend class thin_pool; thin(thin_dev_t dev, thin_pool &pool); + thin(thin_dev_t dev, thin_pool &pool, + device_tree_detail::device_details const &details); thin_dev_t dev_; thin_pool &pool_; + device_tree_detail::device_details details_; + uint32_t open_count_; + bool changed_; }; class thin_pool { @@ -67,6 +72,7 @@ namespace thin_provisioning { void create_thin(thin_dev_t dev); void create_snap(thin_dev_t dev, thin_dev_t origin); void del(thin_dev_t); + void commit(); void set_transaction_id(uint64_t id); uint64_t get_transaction_id() const; @@ -80,14 +86,22 @@ namespace thin_provisioning { block_address get_nr_free_data_blocks() const; sector_t get_data_block_size() const; block_address get_data_dev_size() const; + uint32_t get_time() const; thin::ptr open_thin(thin_dev_t); private: friend class thin; + typedef std::map device_map; + bool device_exists(thin_dev_t dev) const; + thin::ptr create_device(thin_dev_t dev); + thin::ptr open_device(thin_dev_t dev); + void close_device(thin::ptr device); + void write_changed_details(); metadata::ptr md_; + device_map thin_devices_; }; };