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()) { if (path.parent_path().empty()) {
//We are asked to load the base directory '/'. //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) { if (parentWithAncestors == none) {
return none; return none;
} }
auto parent = std::move(parentWithAncestors->blob); auto parent = std::move(parentWithAncestors->blob);
auto grandparent = std::move(parentWithAncestors->parent); 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()); auto optEntry = parent->GetChild(path.filename().string());
if (optEntry == boost::none) { if (optEntry == boost::none) {
@ -211,17 +209,17 @@ optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
switch(entry.type()) { switch(entry.type()) {
case fspp::Dir::EntryType::DIR: 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: 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: 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"); ASSERT(false, "Switch/case not exhaustive");
} }
optional<CryDevice::DirBlobWithAncestors> CryDevice::LoadDirBlobWithAncestors(const bf::path &path) { optional<CryDevice::DirBlobWithAncestors> CryDevice::LoadDirBlobWithAncestors(const bf::path &path, boost::optional<std::vector<BlockId>*> append_ancestors_to) {
auto blob = LoadBlobWithAncestors(path); auto blob = LoadBlobWithAncestors(path, std::move(append_ancestors_to));
if (blob == none) { if (blob == none) {
return none; return none;
} }
@ -229,11 +227,10 @@ optional<CryDevice::DirBlobWithAncestors> CryDevice::LoadDirBlobWithAncestors(co
if (dir == none) { if (dir == none) {
throw FuseErrnoException(ENOTDIR); // Loaded blob is not a directory 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) { optional<CryDevice::BlobWithAncestors> CryDevice::LoadBlobWithAncestors(const bf::path &path, boost::optional<std::vector<BlockId>*> append_ancestors_to) {
std::vector<blockstore::BlockId> ancestors;
optional<unique_ref<DirBlobRef>> parentBlob = none; optional<unique_ref<DirBlobRef>> parentBlob = none;
optional<unique_ref<FsBlobRef>> currentBlobOpt = _fsBlobStore->load(_rootBlobId); optional<unique_ref<FsBlobRef>> currentBlobOpt = _fsBlobStore->load(_rootBlobId);
if (currentBlobOpt == none) { 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"); ASSERT(currentBlob->parentPointer() == BlockId::Null(), "Root Blob should have a nullptr as parent");
for (const bf::path &component : path.relative_path()) { 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); auto currentDir = dynamic_pointer_move<DirBlobRef>(currentBlob);
if (currentDir == none) { if (currentDir == none) {
throw FuseErrnoException(ENOTDIR); // Path component is not a dir 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"); 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) //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" // 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 { struct DirBlobWithAncestors {
cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> blob; cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> blob;
boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent; 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 RemoveBlob(const blockstore::BlockId &blockId);
void onFsAction(std::function<void()> callback); void onFsAction(std::function<void()> callback);
@ -69,9 +68,8 @@ private:
struct BlobWithAncestors { struct BlobWithAncestors {
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> blob; cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> blob;
boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent; 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); DISALLOW_COPY_AND_ASSIGN(CryDevice);
}; };

View File

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

View File

@ -10,7 +10,7 @@ namespace cryfs {
class CryDir final: public fspp::Dir, public CryNode { class CryDir final: public fspp::Dir, public CryNode {
public: 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(); ~CryDir();
//TODO return type variance to CryFile/CryDir? //TODO return type variance to CryFile/CryDir?

View File

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

View File

@ -11,7 +11,7 @@ namespace cryfs {
class CryFile final: public fspp::File, public CryNode { class CryFile final: public fspp::File, public CryNode {
public: 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(); ~CryFile();
cpputils::unique_ref<fspp::OpenFile> open(fspp::openflags_t flags) override; 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::optional;
using boost::none; using boost::none;
using std::shared_ptr; using std::shared_ptr;
using std::vector;
using cryfs::parallelaccessfsblobstore::FsBlobRef; using cryfs::parallelaccessfsblobstore::FsBlobRef;
using cryfs::parallelaccessfsblobstore::DirBlobRef; using cryfs::parallelaccessfsblobstore::DirBlobRef;
using namespace cpputils::logging; using namespace cpputils::logging;
@ -27,11 +28,10 @@ using fspp::fuse::FuseErrnoException;
namespace cryfs { 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), : _device(device),
_parent(none), _parent(none),
_grandparent(none), _grandparent(none),
_ancestors(std::move(ancestors)),
_blockId(blockId) { _blockId(blockId) {
ASSERT(parent != none || grandparent == none, "Grandparent can only be set when parent is not none"); 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); throw FuseErrnoException(EBUSY);
} }
auto targetParentAndAncestors = _device->LoadDirBlobWithAncestors(to.parent_path()); vector<BlockId> targetAncestors;
auto targetParentAndAncestors = _device->LoadDirBlobWithAncestors(to.parent_path(), &targetAncestors);
if (targetParentAndAncestors == none) { if (targetParentAndAncestors == none) {
// Target parent directory doesn't exist // Target parent directory doesn't exist
throw FuseErrnoException(ENOENT); throw FuseErrnoException(ENOENT);
} }
auto targetParent = std::move(targetParentAndAncestors->blob); auto targetParent = std::move(targetParentAndAncestors->blob);
auto targetGrandparent = std::move(targetParentAndAncestors->parent); 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, so it wasn't filled in, but it's a target ancestor
targetAncestors.push_back(targetParent->blockId()); // targetParent is not an ancestor of the targetParent, but it's a target ancestor
if (std::find(targetAncestors.begin(), targetAncestors.end(), _blockId) != targetAncestors.end()) { 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. // 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(); 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. // 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; void access(int mask) const override;
stat_info stat() const override; stat_info stat() const override;
@ -51,7 +51,6 @@ private:
CryDevice *_device; CryDevice *_device;
boost::optional<std::shared_ptr<parallelaccessfsblobstore::DirBlobRef>> _parent; boost::optional<std::shared_ptr<parallelaccessfsblobstore::DirBlobRef>> _parent;
boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> _grandparent; 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; blockstore::BlockId _blockId;
DISALLOW_COPY_AND_ASSIGN(CryNode); DISALLOW_COPY_AND_ASSIGN(CryNode);

View File

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

View File

@ -11,7 +11,7 @@ namespace cryfs {
class CrySymlink final: public fspp::Symlink, public CryNode { class CrySymlink final: public fspp::Symlink, public CryNode {
public: 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(); ~CrySymlink();
boost::filesystem::path target() override; boost::filesystem::path target() override;