Make parent pointer migration interrupt-safe
This commit is contained in:
parent
5386f5b0c9
commit
a19b2281f7
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user