If a migration was interrupted, continue on next mount

This commit is contained in:
Sebastian Messmer 2019-01-21 01:27:32 -08:00
parent ad6125a7e4
commit 652a95dd0d
5 changed files with 32 additions and 2 deletions

View File

@ -32,6 +32,7 @@ CryConfig::CryConfig()
, _exclusiveClientId(none)
#ifndef CRYFS_NO_COMPATIBILITY
, _hasVersionNumbers(true)
, _hasParentPointers(true)
#endif
{
}
@ -53,6 +54,7 @@ CryConfig CryConfig::load(const Data &data) {
cfg._exclusiveClientId = pt.get_optional<uint32_t>("cryfs.exclusiveClientId");
#ifndef CRYFS_NO_COMPATIBILITY
cfg._hasVersionNumbers = pt.get<bool>("cryfs.migrations.hasVersionNumbers", false);
cfg._hasParentPointers = pt.get<bool>("cryfs.migrations.hasParentPointers", false);
#endif
optional<string> filesystemIdOpt = pt.get_optional<string>("cryfs.filesystemId");
@ -81,6 +83,7 @@ Data CryConfig::save() const {
}
#ifndef CRYFS_NO_COMPATIBILITY
pt.put<bool>("cryfs.migrations.hasVersionNumbers", _hasVersionNumbers);
pt.put<bool>("cryfs.migrations.hasParentPointers", _hasParentPointers);
#endif
stringstream stream;
@ -172,6 +175,14 @@ bool CryConfig::HasVersionNumbers() const {
void CryConfig::SetHasVersionNumbers(bool value) {
_hasVersionNumbers = value;
}
bool CryConfig::HasParentPointers() const {
return _hasParentPointers;
}
void CryConfig::SetHasParentPointers(bool value) {
_hasParentPointers = value;
}
#endif
}

View File

@ -56,6 +56,11 @@ public:
// Version numbers cannot be disabled, but the file system will be migrated to version numbers automatically.
bool HasVersionNumbers() const;
void SetHasVersionNumbers(bool value);
// This is a trigger to recognize old file systems that didn't have version numbers.
// Version numbers cannot be disabled, but the file system will be migrated to version numbers automatically.
bool HasParentPointers() const;
void SetHasParentPointers(bool value);
#endif
static CryConfig load(const cpputils::Data &data);
@ -73,6 +78,7 @@ private:
boost::optional<uint32_t> _exclusiveClientId;
#ifndef CRYFS_NO_COMPATIBILITY
bool _hasVersionNumbers;
bool _hasParentPointers;
#endif
CryConfig &operator=(const CryConfig &rhs) = delete;

View File

@ -80,7 +80,14 @@ unique_ref<fsblobstore::FsBlobStore> CryDevice::MigrateOrCreateFsBlobStore(uniqu
if ("" == rootBlobId) {
return make_unique_ref<FsBlobStore>(std::move(blobStore));
}
return FsBlobStore::migrateIfNeeded(std::move(blobStore), BlockId::FromString(rootBlobId));
if (!configFile->config()->HasParentPointers()) {
auto result = FsBlobStore::migrateIfNeeded(std::move(blobStore), BlockId::FromString(rootBlobId));
// Don't migrate again if it was successful
configFile->config()->SetHasParentPointers(true);
configFile->save();
return result;
}
return make_unique_ref<FsBlobStore>(std::move(blobStore));
}
#endif
@ -106,6 +113,7 @@ unique_ref<BlockStore2> CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref
if (!configFile->config()->HasVersionNumbers()) {
IntegrityBlockStore2::migrateFromBlockstoreWithoutVersionNumbers(encryptedBlockStore.get(), integrityFilePath, myClientId);
configFile->config()->SetBlocksizeBytes(configFile->config()->BlocksizeBytes() + IntegrityBlockStore2::HEADER_LENGTH - blockstore::BlockId::BINARY_LENGTH); // Minus BlockId size because EncryptedBlockStore doesn't store the BlockId anymore (that was moved to IntegrityBlockStore)
// Don't migrate again if it was successful
configFile->config()->SetHasVersionNumbers(true);
configFile->save();
}

View File

@ -2,6 +2,7 @@
#include "FileBlob.h"
#include "DirBlob.h"
#include "SymlinkBlob.h"
#include <cryfs/config/CryConfigFile.h>
using cpputils::unique_ref;
using cpputils::make_unique_ref;

View File

@ -10,7 +10,11 @@ namespace cryfs {
void FsBlobView::migrate(blobstore::Blob *blob, const blockstore::BlockId &parentId) {
constexpr unsigned int OLD_HEADER_SIZE = sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t);
ASSERT(FsBlobView::getFormatVersionHeader(*blob) == 0, "Block already migrated");
if(FsBlobView::getFormatVersionHeader(*blob) != 0) {
// blob already migrated
return;
}
// Resize blob and move data back
cpputils::Data data = blob->readAll();
blob->resize(blob->size() + blockstore::BlockId::BINARY_LENGTH);