[block-manager] ensure the superblock cannot be taken concurrently with any other lock.

This commit is contained in:
Joe Thornber 2014-08-21 12:18:05 +01:00
parent 3724f78a13
commit 0d3942cae8
4 changed files with 13 additions and 1 deletions

View File

@ -504,6 +504,12 @@ block_cache::get_nr_blocks() const
return nr_data_blocks_; return nr_data_blocks_;
} }
uint64_t
block_cache::get_nr_locked() const
{
return nr_locked_;
}
void void
block_cache::zero_block(block &b) block_cache::zero_block(block &b)
{ {

View File

@ -119,6 +119,7 @@ namespace bcache {
~block_cache(); ~block_cache();
uint64_t get_nr_blocks() const; uint64_t get_nr_blocks() const;
uint64_t get_nr_locked() const;
enum get_flags { enum get_flags {
GF_ZERO = (1 << 0), GF_ZERO = (1 << 0),

View File

@ -36,7 +36,6 @@
namespace persistent_data { namespace persistent_data {
using namespace bcache; using namespace bcache;
uint32_t const MD_BLOCK_SIZE = 4096; uint32_t const MD_BLOCK_SIZE = 4096;
template <uint32_t BlockSize = MD_BLOCK_SIZE> template <uint32_t BlockSize = MD_BLOCK_SIZE>

View File

@ -268,6 +268,9 @@ namespace persistent_data {
block_manager<BlockSize>::superblock(block_address location, block_manager<BlockSize>::superblock(block_address location,
typename bcache::validator::ptr v) typename bcache::validator::ptr v)
{ {
if (bc_.get_nr_locked() > 0)
throw std::runtime_error("attempt to lock superblock while other locks are still held");
block_cache::block &b = bc_.get(location, block_cache::GF_BARRIER, v); block_cache::block &b = bc_.get(location, block_cache::GF_BARRIER, v);
return write_ref(b, superblock_ref_count_); return write_ref(b, superblock_ref_count_);
} }
@ -277,6 +280,9 @@ namespace persistent_data {
block_manager<BlockSize>::superblock_zero(block_address location, block_manager<BlockSize>::superblock_zero(block_address location,
typename bcache::validator::ptr v) typename bcache::validator::ptr v)
{ {
if (bc_.get_nr_locked() > 0)
throw std::runtime_error("attempt to lock superblock while other locks are still held");
block_cache::block &b = bc_.get(location, block_cache::GF_ZERO | block_cache::GF_BARRIER, v); block_cache::block &b = bc_.get(location, block_cache::GF_ZERO | block_cache::GF_BARRIER, v);
return write_ref(b, superblock_ref_count_); return write_ref(b, superblock_ref_count_);
} }