We don't actually need to calculate or store the ancestor chain unless we're renaming

This commit is contained in:
Sebastian Messmer 2022-12-18 16:34:16 +01:00
parent 222ef46d8d
commit 45895d8d4f
10 changed files with 30 additions and 34 deletions

View File

@ -191,17 +191,15 @@ optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
if (path.parent_path().empty()) {
//We are asked to load the base directory '/'.
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, none, none, _rootBlobId, std::vector<BlockId>()));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, none, none, _rootBlobId));
}
auto parentWithAncestors = LoadDirBlobWithAncestors(path.parent_path());
auto parentWithAncestors = LoadDirBlobWithAncestors(path.parent_path(), none);
if (parentWithAncestors == none) {
return none;
}
auto parent = std::move(parentWithAncestors->blob);
auto grandparent = std::move(parentWithAncestors->parent);
auto ancestors = std::move(parentWithAncestors->ancestors);
ancestors.push_back(parent->blockId()); // parent's ancestors don't contain parent yet, but parent is our ancestor
auto optEntry = parent->GetChild(path.filename().string());
if (optEntry == boost::none) {
@ -211,17 +209,17 @@ optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
switch(entry.type()) {
case fspp::Dir::EntryType::DIR:
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, std::move(parent), std::move(grandparent), entry.blockId(), std::move(ancestors)));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, std::move(parent), std::move(grandparent), entry.blockId()));
case fspp::Dir::EntryType::FILE:
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryFile>(this, std::move(parent), std::move(grandparent), entry.blockId(), std::move(ancestors)));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryFile>(this, std::move(parent), std::move(grandparent), entry.blockId()));
case fspp::Dir::EntryType::SYMLINK:
return optional<unique_ref<fspp::Node>>(make_unique_ref<CrySymlink>(this, std::move(parent), std::move(grandparent), entry.blockId(), std::move(ancestors)));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CrySymlink>(this, std::move(parent), std::move(grandparent), entry.blockId()));
}
ASSERT(false, "Switch/case not exhaustive");
}
optional<CryDevice::DirBlobWithAncestors> CryDevice::LoadDirBlobWithAncestors(const bf::path &path) {
auto blob = LoadBlobWithAncestors(path);
optional<CryDevice::DirBlobWithAncestors> CryDevice::LoadDirBlobWithAncestors(const bf::path &path, boost::optional<std::vector<BlockId>*> append_ancestors_to) {
auto blob = LoadBlobWithAncestors(path, std::move(append_ancestors_to));
if (blob == none) {
return none;
}
@ -229,11 +227,10 @@ optional<CryDevice::DirBlobWithAncestors> CryDevice::LoadDirBlobWithAncestors(co
if (dir == none) {
throw FuseErrnoException(ENOTDIR); // Loaded blob is not a directory
}
return DirBlobWithAncestors{std::move(*dir), std::move(blob->parent), std::move(blob->ancestors)};
return DirBlobWithAncestors{std::move(*dir), std::move(blob->parent)};
}
optional<CryDevice::BlobWithAncestors> CryDevice::LoadBlobWithAncestors(const bf::path &path) {
std::vector<blockstore::BlockId> ancestors;
optional<CryDevice::BlobWithAncestors> CryDevice::LoadBlobWithAncestors(const bf::path &path, boost::optional<std::vector<BlockId>*> append_ancestors_to) {
optional<unique_ref<DirBlobRef>> parentBlob = none;
optional<unique_ref<FsBlobRef>> currentBlobOpt = _fsBlobStore->load(_rootBlobId);
if (currentBlobOpt == none) {
@ -244,7 +241,9 @@ optional<CryDevice::BlobWithAncestors> CryDevice::LoadBlobWithAncestors(const bf
ASSERT(currentBlob->parentPointer() == BlockId::Null(), "Root Blob should have a nullptr as parent");
for (const bf::path &component : path.relative_path()) {
ancestors.push_back(currentBlob->blockId());
if (append_ancestors_to != boost::none) {
(*append_ancestors_to)->push_back(currentBlob->blockId());
}
auto currentDir = dynamic_pointer_move<DirBlobRef>(currentBlob);
if (currentDir == none) {
throw FuseErrnoException(ENOTDIR); // Path component is not a dir
@ -265,7 +264,7 @@ optional<CryDevice::BlobWithAncestors> CryDevice::LoadBlobWithAncestors(const bf
ASSERT(currentBlob->parentPointer() == (*parentBlob)->blockId(), "Blob has wrong parent pointer");
}
return BlobWithAncestors{std::move(currentBlob), std::move(parentBlob), std::move(ancestors)};
return BlobWithAncestors{std::move(currentBlob), std::move(parentBlob)};
//TODO (I think this is resolved, but I should test it)
// Running the python script, waiting for "Create files in sequential order...", then going into dir ~/tmp/cryfs-mount-.../Bonnie.../ and calling "ls"

View File

@ -31,9 +31,8 @@ public:
struct DirBlobWithAncestors {
cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> blob;
boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent;
std::vector<blockstore::BlockId> ancestors;
};
boost::optional<DirBlobWithAncestors> LoadDirBlobWithAncestors(const boost::filesystem::path &path);
boost::optional<DirBlobWithAncestors> LoadDirBlobWithAncestors(const boost::filesystem::path &path, boost::optional<std::vector<blockstore::BlockId>*> append_ancestors_to);
void RemoveBlob(const blockstore::BlockId &blockId);
void onFsAction(std::function<void()> callback);
@ -69,9 +68,8 @@ private:
struct BlobWithAncestors {
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> blob;
boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent;
std::vector<blockstore::BlockId> ancestors;
};
boost::optional<BlobWithAncestors> LoadBlobWithAncestors(const boost::filesystem::path &path);
boost::optional<BlobWithAncestors> LoadBlobWithAncestors(const boost::filesystem::path &path, boost::optional<std::vector<blockstore::BlockId>*> append_ancestors_to);
DISALLOW_COPY_AND_ASSIGN(CryDevice);
};

View File

@ -28,8 +28,8 @@ using cryfs::parallelaccessfsblobstore::DirBlobRef;
namespace cryfs {
CryDir::CryDir(CryDevice *device, optional<unique_ref<DirBlobRef>> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId, std::vector<BlockId> ancestors)
: CryNode(device, std::move(parent), std::move(grandparent), blockId, std::move(ancestors)) {
CryDir::CryDir(CryDevice *device, optional<unique_ref<DirBlobRef>> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId)
: CryNode(device, std::move(parent), std::move(grandparent), blockId) {
}
CryDir::~CryDir() {

View File

@ -10,7 +10,7 @@ namespace cryfs {
class CryDir final: public fspp::Dir, public CryNode {
public:
CryDir(CryDevice *device, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId, std::vector<blockstore::BlockId> ancestors);
CryDir(CryDevice *device, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId);
~CryDir();
//TODO return type variance to CryFile/CryDir?

View File

@ -18,8 +18,8 @@ using cryfs::parallelaccessfsblobstore::FileBlobRef;
namespace cryfs {
CryFile::CryFile(CryDevice *device, unique_ref<DirBlobRef> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId, std::vector<BlockId> ancestors)
: CryNode(device, std::move(parent), std::move(grandparent), blockId, std::move(ancestors)) {
CryFile::CryFile(CryDevice *device, unique_ref<DirBlobRef> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId)
: CryNode(device, std::move(parent), std::move(grandparent), blockId) {
}
CryFile::~CryFile() {

View File

@ -11,7 +11,7 @@ namespace cryfs {
class CryFile final: public fspp::File, public CryNode {
public:
CryFile(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId, std::vector<blockstore::BlockId> ancestors);
CryFile(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId);
~CryFile();
cpputils::unique_ref<fspp::OpenFile> open(fspp::openflags_t flags) override;

View File

@ -18,6 +18,7 @@ using cpputils::dynamic_pointer_move;
using boost::optional;
using boost::none;
using std::shared_ptr;
using std::vector;
using cryfs::parallelaccessfsblobstore::FsBlobRef;
using cryfs::parallelaccessfsblobstore::DirBlobRef;
using namespace cpputils::logging;
@ -27,11 +28,10 @@ using fspp::fuse::FuseErrnoException;
namespace cryfs {
CryNode::CryNode(CryDevice *device, optional<unique_ref<DirBlobRef>> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId, std::vector<BlockId> ancestors)
CryNode::CryNode(CryDevice *device, optional<unique_ref<DirBlobRef>> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId)
: _device(device),
_parent(none),
_grandparent(none),
_ancestors(std::move(ancestors)),
_blockId(blockId) {
ASSERT(parent != none || grandparent == none, "Grandparent can only be set when parent is not none");
@ -88,15 +88,15 @@ void CryNode::rename(const bf::path &to) {
throw FuseErrnoException(EBUSY);
}
auto targetParentAndAncestors = _device->LoadDirBlobWithAncestors(to.parent_path());
vector<BlockId> targetAncestors;
auto targetParentAndAncestors = _device->LoadDirBlobWithAncestors(to.parent_path(), &targetAncestors);
if (targetParentAndAncestors == none) {
// Target parent directory doesn't exist
throw FuseErrnoException(ENOENT);
}
auto targetParent = std::move(targetParentAndAncestors->blob);
auto targetGrandparent = std::move(targetParentAndAncestors->parent);
auto targetAncestors = std::move(targetParentAndAncestors->ancestors);
targetAncestors.push_back(targetParent->blockId()); // targetParent is not an ancestor of the targetParent, but it's a target ancestor
targetAncestors.push_back(targetParent->blockId()); // targetParent is not an ancestor of the targetParent, so it wasn't filled in, but it's a target ancestor
if (std::find(targetAncestors.begin(), targetAncestors.end(), _blockId) != targetAncestors.end()) {
// We are trying to move a node into one of its subdirectories. This is not allowed.

View File

@ -15,7 +15,7 @@ public:
virtual ~CryNode();
// TODO grandparent is only needed to set the timestamps of the parent directory on rename and remove. Delete grandparent parameter once we store timestamps in the blob itself instead of in the directory listing.
CryNode(CryDevice *device, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId, std::vector<blockstore::BlockId> ancestors);
CryNode(CryDevice *device, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId);
void access(int mask) const override;
stat_info stat() const override;
@ -51,7 +51,6 @@ private:
CryDevice *_device;
boost::optional<std::shared_ptr<parallelaccessfsblobstore::DirBlobRef>> _parent;
boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> _grandparent;
std::vector<blockstore::BlockId> _ancestors; // [n-1] is the parent, [n-2] is the grandparent, ..., [0] is the file system root,
blockstore::BlockId _blockId;
DISALLOW_COPY_AND_ASSIGN(CryNode);

View File

@ -21,8 +21,8 @@ using cryfs::parallelaccessfsblobstore::DirBlobRef;
namespace cryfs {
CrySymlink::CrySymlink(CryDevice *device, unique_ref<DirBlobRef> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId, std::vector<blockstore::BlockId> ancestors)
: CryNode(device, std::move(parent), std::move(grandparent), blockId, std::move(ancestors)) {
CrySymlink::CrySymlink(CryDevice *device, unique_ref<DirBlobRef> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId)
: CryNode(device, std::move(parent), std::move(grandparent), blockId) {
}
CrySymlink::~CrySymlink() {

View File

@ -11,7 +11,7 @@ namespace cryfs {
class CrySymlink final: public fspp::Symlink, public CryNode {
public:
CrySymlink(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId, std::vector<blockstore::BlockId> ancestors);
CrySymlink(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId);
~CrySymlink();
boost::filesystem::path target() override;