Make parent pointer migration interrupt-safe

This commit is contained in:
Sebastian Messmer 2019-01-21 20:55:56 -08:00
parent 5386f5b0c9
commit a19b2281f7
3 changed files with 22 additions and 14 deletions

View File

@ -81,7 +81,7 @@ unique_ref<fsblobstore::FsBlobStore> CryDevice::MigrateOrCreateFsBlobStore(uniqu
return make_unique_ref<FsBlobStore>(std::move(blobStore));
}
if (!configFile->config()->HasParentPointers()) {
auto result = FsBlobStore::migrateIfNeeded(std::move(blobStore), BlockId::FromString(rootBlobId));
auto result = FsBlobStore::migrate(std::move(blobStore), BlockId::FromString(rootBlobId));
// Don't migrate again if it was successful
configFile->config()->SetHasParentPointers(true);
configFile->save();

View File

@ -7,6 +7,7 @@
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::SignalCatcher;
using blobstore::BlobStore;
using blockstore::BlockId;
using boost::none;
@ -33,33 +34,37 @@ boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::BlockId
}
#ifndef CRYFS_NO_COMPATIBILITY
unique_ref<FsBlobStore> FsBlobStore::migrateIfNeeded(unique_ref<BlobStore> blobStore, const blockstore::BlockId &rootBlobId) {
unique_ref<FsBlobStore> FsBlobStore::migrate(unique_ref<BlobStore> blobStore, const blockstore::BlockId &rootBlobId) {
SignalCatcher signalCatcher;
auto rootBlob = blobStore->load(rootBlobId);
ASSERT(rootBlob != none, "Could not load root blob");
uint16_t format = FsBlobView::getFormatVersionHeader(**rootBlob);
auto fsBlobStore = make_unique_ref<FsBlobStore>(std::move(blobStore));
if (format == 0) {
// migration needed
std::cout << "Migrating file system for conflict resolution features. Please don't interrupt this process. This can take a while..." << std::flush;
fsBlobStore->_migrate(std::move(*rootBlob), blockstore::BlockId::Null());
std::cout << "done" << std::endl;
}
std::cout << "Migrating file system for conflict resolution features. Please don't interrupt this process. This can take a while..." << std::flush;
fsBlobStore->_migrate(std::move(*rootBlob), blockstore::BlockId::Null(), &signalCatcher);
std::cout << "done" << std::endl;
return fsBlobStore;
}
void FsBlobStore::_migrate(unique_ref<blobstore::Blob> node, const blockstore::BlockId &parentId) {
void FsBlobStore::_migrate(unique_ref<blobstore::Blob> node, const blockstore::BlockId &parentId, SignalCatcher* signalCatcher) {
FsBlobView::migrate(node.get(), parentId);
if (FsBlobView::blobType(*node) == FsBlobView::BlobType::DIR) {
DirBlob dir(std::move(node), _getLstatSize());
vector<fspp::Dir::Entry> children;
dir.AppendChildrenTo(&children);
for (const auto &child : children) {
if (signalCatcher->signal_occurred()) {
// on a SIGINT or SIGTERM, cancel migration but gracefully shutdown, i.e. call destructors.
throw std::runtime_error("Caught signal");
}
auto childEntry = dir.GetChild(child.name);
ASSERT(childEntry != none, "Couldn't load child, although it was returned as a child in the lsit.");
ASSERT(childEntry != none, "Couldn't load child, although it was returned as a child in the list.");
auto childBlob = _baseBlobStore->load(childEntry->blockId());
ASSERT(childBlob != none, "Couldn't load child blob");
_migrate(std::move(*childBlob), dir.blockId());
_migrate(std::move(*childBlob), dir.blockId(), signalCatcher);
}
}
}

View File

@ -8,6 +8,9 @@
#include "FileBlob.h"
#include "DirBlob.h"
#include "SymlinkBlob.h"
#ifndef CRYFS_NO_COMPATIBILITY
#include <cpp-utils/process/SignalCatcher.h>
#endif
namespace cryfs {
namespace fsblobstore {
@ -29,13 +32,13 @@ namespace cryfs {
uint64_t virtualBlocksizeBytes() const;
#ifndef CRYFS_NO_COMPATIBILITY
static cpputils::unique_ref<FsBlobStore> migrateIfNeeded(cpputils::unique_ref<blobstore::BlobStore> blobStore, const blockstore::BlockId &blockId);
static cpputils::unique_ref<FsBlobStore> migrate(cpputils::unique_ref<blobstore::BlobStore> blobStore, const blockstore::BlockId &blockId);
#endif
private:
#ifndef CRYFS_NO_COMPATIBILITY
void _migrate(cpputils::unique_ref<blobstore::Blob> node, const blockstore::BlockId &parentId);
void _migrate(cpputils::unique_ref<blobstore::Blob> node, const blockstore::BlockId &parentId, cpputils::SignalCatcher* signalCatcher);
#endif
std::function<fspp::num_bytes_t(const blockstore::BlockId &)> _getLstatSize();