Make integrity migration interrupt-safe

This commit is contained in:
Sebastian Messmer 2019-01-21 22:25:58 -08:00
parent a19b2281f7
commit a3a9f25e02

View File

@ -2,11 +2,13 @@
#include "IntegrityBlockStore2.h"
#include "KnownBlockVersions.h"
#include <cpp-utils/data/SerializationHelper.h>
#include <cpp-utils/process/SignalCatcher.h>
using cpputils::Data;
using cpputils::unique_ref;
using cpputils::serialize;
using cpputils::deserialize;
using cpputils::SignalCatcher;
using std::string;
using boost::optional;
using boost::none;
@ -195,22 +197,31 @@ void IntegrityBlockStore2::forEachBlock(std::function<void (const BlockId &)> ca
#ifndef CRYFS_NO_COMPATIBILITY
void IntegrityBlockStore2::migrateFromBlockstoreWithoutVersionNumbers(BlockStore2 *baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId) {
SignalCatcher signalCatcher;
std::cout << "Migrating file system for integrity features. Please don't interrupt this process. This can take a while..." << std::flush;
KnownBlockVersions knownBlockVersions(integrityFilePath, myClientId);
baseBlockStore->forEachBlock([&baseBlockStore, &knownBlockVersions] (const BlockId &blockId) {
baseBlockStore->forEachBlock([&baseBlockStore, &knownBlockVersions, &signalCatcher] (const BlockId &blockId) {
if (signalCatcher.signal_occurred()) {
throw std::runtime_error("Caught signal");
}
migrateBlockFromBlockstoreWithoutVersionNumbers(baseBlockStore, blockId, &knownBlockVersions);
});
std::cout << "done" << std::endl;
}
void IntegrityBlockStore2::migrateBlockFromBlockstoreWithoutVersionNumbers(blockstore::BlockStore2* baseBlockStore, const blockstore::BlockId& blockId, KnownBlockVersions *knownBlockVersions) {
uint64_t version = knownBlockVersions->incrementVersion(blockId);
auto data_ = baseBlockStore->load(blockId);
if (data_ == boost::none) {
LOG(WARN, "Block not found, but was returned from forEachBlock before");
return;
}
if (0 != _readFormatHeader(*data_)) {
// already migrated
return;
}
uint64_t version = knownBlockVersions->incrementVersion(blockId);
cpputils::Data data = std::move(*data_);
cpputils::Data dataWithHeader = _prependHeaderToData(blockId, knownBlockVersions->myClientId(), version, data);
baseBlockStore->store(blockId, dataWithHeader);