diff --git a/persistent-data/block.tcc b/persistent-data/block.tcc index be55c23..e9da86a 100644 --- a/persistent-data/block.tcc +++ b/persistent-data/block.tcc @@ -325,7 +325,7 @@ typename block_manager::write_ref block_manager::superblock(block_address location, typename block_manager::validator::ptr v) { - tracker_.write_lock(location); + tracker_.superblock_lock(location); try { check(location); @@ -353,7 +353,7 @@ typename block_manager::write_ref block_manager::superblock_zero(block_address location, typename block_manager::validator::ptr v) { - tracker_.write_lock(location); + tracker_.superblock_lock(location); try { check(location); diff --git a/persistent-data/lock_tracker.cc b/persistent-data/lock_tracker.cc index b7c3f48..b21aa54 100644 --- a/persistent-data/lock_tracker.cc +++ b/persistent-data/lock_tracker.cc @@ -59,6 +59,21 @@ lock_tracker::write_lock(uint64_t key) locks_.insert(make_pair(key, -1)); } +void +lock_tracker::superblock_lock(uint64_t key) +{ + if (superblock_) + throw runtime_error("superblock already held"); + + superblock_ = boost::optional(key); + try { + write_lock(key); + + } catch (...) { + superblock_ = boost::optional(); + } +} + void lock_tracker::unlock(uint64_t key) { @@ -72,6 +87,9 @@ lock_tracker::unlock(uint64_t key) locks_.insert(make_pair(key, it->second - 1)); else locks_.erase(key); + + if (superblock_ && *superblock_ == key) + superblock_ = boost::optional(); } bool diff --git a/persistent-data/lock_tracker.h b/persistent-data/lock_tracker.h index 8541d83..f54ad42 100644 --- a/persistent-data/lock_tracker.h +++ b/persistent-data/lock_tracker.h @@ -20,6 +20,7 @@ #define LOCK_TRACKER_H #include +#include #include #include @@ -33,6 +34,7 @@ namespace persistent_data { void read_lock(uint64_t key); void write_lock(uint64_t key); + void superblock_lock(uint64_t key); void unlock(uint64_t key); private: @@ -45,6 +47,7 @@ namespace persistent_data { // Positive for read lock, negative for write lock LockMap locks_; + boost::optional superblock_; uint64_t low_; uint64_t high_;