New way of handling block deletions: Set last-update-client-id to zero instead of increasing version number. This has the same effect (i.e. invalidates all known block versions) and it additionally allows for checking in a local list whether a block is deleted or not.

This commit is contained in:
Sebastian Messmer 2016-06-25 14:25:19 -07:00
parent ee1f0f4d3a
commit fd5dd2c6e1
4 changed files with 15 additions and 7 deletions

View File

@ -19,6 +19,7 @@ namespace blockstore {
namespace versioncounting { namespace versioncounting {
const string KnownBlockVersions::HEADER = "cryfs.integritydata.knownblockversions;0"; const string KnownBlockVersions::HEADER = "cryfs.integritydata.knownblockversions;0";
constexpr uint32_t KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK;
KnownBlockVersions::KnownBlockVersions(const bf::path &stateFilePath) KnownBlockVersions::KnownBlockVersions(const bf::path &stateFilePath)
:_knownVersions(), _lastUpdateClientId(), _stateFilePath(stateFilePath), _myClientId(0), _mutex(), _valid(true) { :_knownVersions(), _lastUpdateClientId(), _stateFilePath(stateFilePath), _myClientId(0), _mutex(), _valid(true) {
@ -46,6 +47,7 @@ KnownBlockVersions::~KnownBlockVersions() {
bool KnownBlockVersions::checkAndUpdateVersion(uint32_t clientId, const Key &key, uint64_t version) { bool KnownBlockVersions::checkAndUpdateVersion(uint32_t clientId, const Key &key, uint64_t version) {
unique_lock<mutex> lock(_mutex); unique_lock<mutex> lock(_mutex);
ASSERT(clientId != CLIENT_ID_FOR_DELETED_BLOCK, "This is not a valid client id");
ASSERT(version > 0, "Version has to be >0"); // Otherwise we wouldn't handle notexisting entries correctly. ASSERT(version > 0, "Version has to be >0"); // Otherwise we wouldn't handle notexisting entries correctly.
ASSERT(_valid, "Object not valid due to a std::move"); ASSERT(_valid, "Object not valid due to a std::move");
@ -85,7 +87,9 @@ void KnownBlockVersions::_loadStateFile() {
optional<Data> file = Data::LoadFromFile(_stateFilePath); optional<Data> file = Data::LoadFromFile(_stateFilePath);
if (file == none) { if (file == none) {
// File doesn't exist means we loaded empty state. Assign a random client id. // File doesn't exist means we loaded empty state. Assign a random client id.
do {
_myClientId = *reinterpret_cast<uint32_t*>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data()); _myClientId = *reinterpret_cast<uint32_t*>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data());
} while(_myClientId == CLIENT_ID_FOR_DELETED_BLOCK); // Safety check - CLIENT_ID_FOR_DELETED_BLOCK shouldn't be used by any valid client.
return; return;
} }
@ -183,8 +187,13 @@ uint32_t KnownBlockVersions::myClientId() const {
} }
uint64_t KnownBlockVersions::getBlockVersion(uint32_t clientId, const Key &key) const { uint64_t KnownBlockVersions::getBlockVersion(uint32_t clientId, const Key &key) const {
unique_lock<mutex> lock(_mutex);
return _knownVersions.at({clientId, key}); return _knownVersions.at({clientId, key});
} }
void KnownBlockVersions::markBlockAsDeleted(const Key &key) {
_lastUpdateClientId[key] = CLIENT_ID_FOR_DELETED_BLOCK;
}
} }
} }

View File

@ -25,6 +25,8 @@ namespace blockstore {
uint64_t incrementVersion(const Key &key, uint64_t lastVersion); uint64_t incrementVersion(const Key &key, uint64_t lastVersion);
void markBlockAsDeleted(const Key &key);
uint64_t getBlockVersion(uint32_t clientId, const Key &key) const; uint64_t getBlockVersion(uint32_t clientId, const Key &key) const;
uint32_t myClientId() const; uint32_t myClientId() const;
@ -38,6 +40,8 @@ namespace blockstore {
mutable std::mutex _mutex; mutable std::mutex _mutex;
bool _valid; bool _valid;
static constexpr uint32_t CLIENT_ID_FOR_DELETED_BLOCK = 0;
static const std::string HEADER; static const std::string HEADER;
void _loadStateFile(); void _loadStateFile();

View File

@ -41,7 +41,6 @@ public:
size_t size() const override; size_t size() const override;
void resize(size_t newSize) override; void resize(size_t newSize) override;
uint64_t version() const;
cpputils::unique_ref<Block> releaseBlock(); cpputils::unique_ref<Block> releaseBlock();
#ifndef CRYFS_NO_COMPATIBILITY #ifndef CRYFS_NO_COMPATIBILITY
@ -208,10 +207,6 @@ inline uint64_t VersionCountingBlock::blockSizeFromPhysicalBlockSize(uint64_t bl
return blockSize - HEADER_LENGTH; return blockSize - HEADER_LENGTH;
} }
inline uint64_t VersionCountingBlock::version() const {
return _version;
}
} }
} }

View File

@ -66,7 +66,7 @@ inline void VersionCountingBlockStore::remove(cpputils::unique_ref<Block> block)
Key key = block->key(); Key key = block->key();
auto versionCountingBlock = cpputils::dynamic_pointer_move<VersionCountingBlock>(block); auto versionCountingBlock = cpputils::dynamic_pointer_move<VersionCountingBlock>(block);
ASSERT(versionCountingBlock != boost::none, "Block is not an VersionCountingBlock"); ASSERT(versionCountingBlock != boost::none, "Block is not an VersionCountingBlock");
_knownBlockVersions.incrementVersion(key, (*versionCountingBlock)->version()); _knownBlockVersions.markBlockAsDeleted(key);
auto baseBlock = (*versionCountingBlock)->releaseBlock(); auto baseBlock = (*versionCountingBlock)->releaseBlock();
_baseBlockStore->remove(std::move(baseBlock)); _baseBlockStore->remove(std::move(baseBlock));
} }