From a3a9f25e028da2cb6b366c91c24af564dcd6c27c Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Mon, 21 Jan 2019 22:25:58 -0800 Subject: [PATCH] Make integrity migration interrupt-safe --- .../integrity/IntegrityBlockStore2.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/blockstore/implementations/integrity/IntegrityBlockStore2.cpp b/src/blockstore/implementations/integrity/IntegrityBlockStore2.cpp index 62ae8f43..1b37b97b 100644 --- a/src/blockstore/implementations/integrity/IntegrityBlockStore2.cpp +++ b/src/blockstore/implementations/integrity/IntegrityBlockStore2.cpp @@ -2,11 +2,13 @@ #include "IntegrityBlockStore2.h" #include "KnownBlockVersions.h" #include +#include 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 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);