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:
parent
ee1f0f4d3a
commit
fd5dd2c6e1
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user