Skip to content

Commit 72a8d03

Browse files
MichaelCuevasmeta-codesync[bot]
authored andcommitted
Derive UNDER_ACL from local ancestry
Summary: Compute UNDER_ACL from local inode ancestry and direct hasACL metadata instead of issuing remote ACL lookups. VirtualInode now keeps the direct ACL bit separate from inherited ancestor state, computes UNDER_ACL from those two inputs, and keeps local ACL-info population limited to the known-negative case where the ACL list is known empty. Reviewed By: muirdm Differential Revision: D104246345 fbshipit-source-id: f3f7d06eccd961110edfaf301aec5fac41cb0932
1 parent df0aeea commit 72a8d03

13 files changed

Lines changed: 618 additions & 167 deletions

‎eden/fs/config/EdenConfig.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2601,6 +2601,15 @@ class EdenConfig : private ConfigSettingManager {
26012601
300,
26022602
this};
26032603

2604+
/**
2605+
* Whether EdenFS should compute UNDER_ACL and local empty ACL info from
2606+
* source-control tree ACL metadata.
2607+
*/
2608+
ConfigSetting<bool> enableLocalUnderAclComputation{
2609+
"acl:enable-local-under-acl-computation",
2610+
true,
2611+
this};
2612+
26042613
// [facebook]
26052614
// Facebook internal
26062615

‎eden/fs/inodes/AclState.h‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This software may be used and distributed according to the terms of the
5+
* GNU General Public License version 2.
6+
*/
7+
8+
#pragma once
9+
10+
#include <optional>
11+
12+
namespace facebook::eden {
13+
14+
struct AclState {
15+
std::optional<bool> ancestorUnderAcl;
16+
std::optional<bool> hasACL;
17+
};
18+
19+
inline std::optional<bool> mergeAncestorAclState(
20+
std::optional<bool> ancestorUnderAcl,
21+
std::optional<bool> hasACL) {
22+
if (ancestorUnderAcl == true || hasACL == true) {
23+
return true;
24+
}
25+
if (ancestorUnderAcl == false && hasACL == false) {
26+
return false;
27+
}
28+
return std::nullopt;
29+
}
30+
31+
inline AclState adjustRootAclState(
32+
bool isRoot,
33+
std::optional<bool> ancestorUnderAcl,
34+
std::optional<bool> hasACL) {
35+
if (!isRoot || ancestorUnderAcl == true) {
36+
return {ancestorUnderAcl, hasACL};
37+
}
38+
39+
if (hasACL != true) {
40+
hasACL = false;
41+
}
42+
return {false, hasACL};
43+
}
44+
45+
} // namespace facebook::eden

‎eden/fs/inodes/BUCK‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ cpp_library(
101101
"VirtualInode.cpp",
102102
],
103103
headers = [
104+
"AclState.h",
104105
"CacheHint.h",
105106
"CheckoutAction.h",
106107
"CheckoutContext.h",

‎eden/fs/inodes/ChildEntryAttributes.cpp‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,23 @@ namespace facebook::eden {
1616

1717
folly::coro::Task<EntryAttributes> coFetchEntryAttributesFromVI(
1818
VirtualInode v,
19+
std::optional<bool> ancestorUnderAcl,
1920
EntryAttributeFlags reqAttrs,
2021
RelativePath sub,
2122
std::shared_ptr<ObjectStore> store,
2223
timespec checkoutTime,
2324
ObjectFetchContextPtr ctx) {
2425
co_await folly::coro::co_reschedule_on_current_executor;
26+
v.inheritAclFromAncestor(ancestorUnderAcl);
2527
co_return co_await v.co_getEntryAttributes(
2628
reqAttrs, sub, store, checkoutTime, ctx);
2729
}
2830

2931
folly::coro::Task<EntryAttributes> coFetchTreeEntryAttributes(
3032
ObjectId oid,
3133
mode_t mode,
34+
std::optional<bool> hasACL,
35+
std::optional<bool> ancestorUnderAcl,
3236
EntryAttributeFlags reqAttrs,
3337
RelativePath sub,
3438
std::shared_ptr<ObjectStore> store,
@@ -37,19 +41,23 @@ folly::coro::Task<EntryAttributes> coFetchTreeEntryAttributes(
3741
co_await folly::coro::co_reschedule_on_current_executor;
3842
auto t = co_await store->co_getTree(oid, ctx);
3943
VirtualInode v{std::move(t), mode};
44+
v.setHasACL(hasACL);
45+
v.inheritAclFromAncestor(ancestorUnderAcl);
4046
co_return co_await v.co_getEntryAttributes(
4147
reqAttrs, sub, store, checkoutTime, ctx);
4248
}
4349

4450
folly::coro::Task<EntryAttributes> coFetchLoadedInodeEntryAttributes(
4551
folly::SemiFuture<InodePtr> loadFut,
52+
std::optional<bool> ancestorUnderAcl,
4653
EntryAttributeFlags reqAttrs,
4754
RelativePath sub,
4855
std::shared_ptr<ObjectStore> store,
4956
timespec checkoutTime,
5057
ObjectFetchContextPtr ctx) {
5158
auto inode = co_await std::move(loadFut);
5259
VirtualInode v{std::move(inode)};
60+
v.inheritAclFromAncestor(ancestorUnderAcl);
5361
co_return co_await v.co_getEntryAttributes(
5462
reqAttrs, sub, store, checkoutTime, ctx);
5563
}

‎eden/fs/inodes/ChildEntryAttributes.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <folly/futures/Future.h>
1212
#include <sys/types.h>
1313
#include <memory>
14+
#include <optional>
1415

1516
#include "eden/common/utils/PathFuncs.h"
1617
#include "eden/fs/inodes/InodePtrFwd.h"
@@ -45,6 +46,7 @@ class ObjectStore;
4546
*/
4647
folly::coro::Task<EntryAttributes> coFetchEntryAttributesFromVI(
4748
VirtualInode v,
49+
std::optional<bool> ancestorUnderAcl,
4850
EntryAttributeFlags reqAttrs,
4951
RelativePath sub,
5052
std::shared_ptr<ObjectStore> store,
@@ -58,6 +60,8 @@ folly::coro::Task<EntryAttributes> coFetchEntryAttributesFromVI(
5860
folly::coro::Task<EntryAttributes> coFetchTreeEntryAttributes(
5961
ObjectId oid,
6062
mode_t mode,
63+
std::optional<bool> hasACL,
64+
std::optional<bool> ancestorUnderAcl,
6165
EntryAttributeFlags reqAttrs,
6266
RelativePath sub,
6367
std::shared_ptr<ObjectStore> store,
@@ -69,6 +73,7 @@ folly::coro::Task<EntryAttributes> coFetchTreeEntryAttributes(
6973
*/
7074
folly::coro::Task<EntryAttributes> coFetchLoadedInodeEntryAttributes(
7175
folly::SemiFuture<InodePtr> loadFut,
76+
std::optional<bool> ancestorUnderAcl,
7277
EntryAttributeFlags reqAttrs,
7378
RelativePath sub,
7479
std::shared_ptr<ObjectStore> store,

‎eden/fs/inodes/TreeInode.cpp‎

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "eden/fs/config/CheckoutConfig.h"
4040
#include "eden/fs/fuse/FuseChannel.h"
4141
#include "eden/fs/fuse/FuseDirList.h"
42+
#include "eden/fs/inodes/AclState.h"
4243
#include "eden/fs/inodes/CheckoutAction.h"
4344
#include "eden/fs/inodes/CheckoutContext.h"
4445
#include "eden/fs/inodes/ChildEntryAttributes.h"
@@ -595,9 +596,11 @@ std::optional<ImmediateFuture<VirtualInode>> TreeInode::rlockGetOrFindChild(
595596
// the id
596597
return getObjectStore()
597598
.getTree(entry.getObjectId(), context)
598-
.thenValue([mode = entry.getInitialMode()](
599+
.thenValue([mode = entry.getInitialMode(), hasACL = entry.hasACL()](
599600
std::shared_ptr<const Tree>&& tree) {
600-
return VirtualInode(std::move(tree), mode);
601+
auto virtualInode = VirtualInode(std::move(tree), mode);
602+
virtualInode.setHasACL(hasACL);
603+
return virtualInode;
601604
});
602605
}
603606
// This is a file, return the DirEntry if this was the last
@@ -758,7 +761,8 @@ std::optional<VirtualInode> TreeInode::rlockCheckChild(
758761
entry.getInitialMode(),
759762
contents.entries.getCaseSensitivity());
760763
}
761-
dirFetch = PendingDirFetch{entry.getObjectId(), entry.getInitialMode()};
764+
dirFetch = PendingDirFetch{
765+
entry.getObjectId(), entry.getInitialMode(), entry.hasACL()};
762766
return std::nullopt;
763767
}
764768
return VirtualInode{UnmaterializedUnloadedBlobDirEntry(entry)};
@@ -830,7 +834,9 @@ folly::coro::now_task<VirtualInode> TreeInode::co_getOrFindChild(
830834
// All locks released before suspension
831835
if (dirFetch.has_value()) {
832836
auto tree = co_await getObjectStore().co_getTree(dirFetch->treeId, context);
833-
co_return VirtualInode(std::move(tree), dirFetch->mode);
837+
auto virtualInode = VirtualInode(std::move(tree), dirFetch->mode);
838+
virtualInode.setHasACL(dirFetch->hasACL);
839+
co_return virtualInode;
834840
}
835841

836842
auto inode = co_await std::move(loadFuture);
@@ -953,7 +959,9 @@ TreeInode::co_getChildren(
953959
-> folly::coro::Task<VirtualInode> {
954960
co_await folly::coro::co_reschedule_on_current_executor;
955961
auto tree = co_await s->co_getTree(fetch.treeId, ctx);
956-
co_return VirtualInode{std::move(tree), fetch.mode};
962+
auto virtualInode = VirtualInode{std::move(tree), fetch.mode};
963+
virtualInode.setHasACL(fetch.hasACL);
964+
co_return virtualInode;
957965
},
958966
store,
959967
*dirFetch,
@@ -997,7 +1005,8 @@ TreeInode::co_getChildrenAttributes(
9971005
RelativePath path,
9981006
const std::shared_ptr<ObjectStore>& objectStore,
9991007
timespec lastCheckoutTime,
1000-
const ObjectFetchContextPtr& context) {
1008+
const ObjectFetchContextPtr& context,
1009+
std::optional<bool> ancestorUnderAcl) {
10011010
auto self = inodePtrFromThis();
10021011

10031012
if (FOLLY_UNLIKELY(isRestricted())) {
@@ -1022,6 +1031,10 @@ TreeInode::co_getChildrenAttributes(
10221031
names.reserve(contents->entries.size());
10231032
tasks.reserve(contents->entries.size());
10241033
inodeLoadCleanUps.reserve(contents->entries.size());
1034+
auto adjusted = adjustRootAclState(
1035+
getNodeId() == kRootNodeId, ancestorUnderAcl, hasACL());
1036+
auto thisUnderAcl =
1037+
mergeAncestorAclState(adjusted.ancestorUnderAcl, adjusted.hasACL);
10251038

10261039
for (const auto& [name, _entry] : contents->entries) {
10271040
auto subPath = path + name;
@@ -1032,6 +1045,7 @@ TreeInode::co_getChildrenAttributes(
10321045
if (sync.has_value()) {
10331046
tasks.emplace_back(coFetchEntryAttributesFromVI(
10341047
std::move(*sync),
1048+
thisUnderAcl,
10351049
requestedAttributes,
10361050
std::move(subPath),
10371051
objectStore,
@@ -1041,6 +1055,8 @@ TreeInode::co_getChildrenAttributes(
10411055
tasks.emplace_back(coFetchTreeEntryAttributes(
10421056
dirFetch->treeId,
10431057
dirFetch->mode,
1058+
dirFetch->hasACL,
1059+
thisUnderAcl,
10441060
requestedAttributes,
10451061
std::move(subPath),
10461062
objectStore,
@@ -1052,6 +1068,7 @@ TreeInode::co_getChildrenAttributes(
10521068
inodeLoadCleanUps.emplace_back(name, std::move(childResult.second));
10531069
tasks.emplace_back(coFetchLoadedInodeEntryAttributes(
10541070
std::move(childResult.first),
1071+
thisUnderAcl,
10551072
requestedAttributes,
10561073
std::move(subPath),
10571074
objectStore,

‎eden/fs/inodes/TreeInode.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ class TreeInode final : public InodeBaseMetadata<DirContents> {
223223
RelativePath path,
224224
const std::shared_ptr<ObjectStore>& objectStore,
225225
timespec lastCheckoutTime,
226-
const ObjectFetchContextPtr& context);
226+
const ObjectFetchContextPtr& context,
227+
std::optional<bool> ancestorUnderAcl = std::nullopt);
227228

228229
/**
229230
* Get the inode object for a child of this directory.
@@ -1361,6 +1362,7 @@ class TreeInode final : public InodeBaseMetadata<DirContents> {
13611362
struct PendingDirFetch {
13621363
ObjectId treeId;
13631364
mode_t mode{};
1365+
std::optional<bool> hasACL{std::nullopt};
13641366
};
13651367

13661368
std::optional<VirtualInode> rlockCheckChild(

‎eden/fs/inodes/UnmaterializedUnloadedBlobDirEntry.h‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#pragma once
99

10+
#include <optional>
11+
1012
#include "eden/common/utils/DirType.h"
1113
#include "eden/fs/inodes/DirEntry.h"
1214
#include "eden/fs/model/ObjectId.h"
@@ -35,7 +37,7 @@ class UnmaterializedUnloadedBlobDirEntry {
3537
: objectId_(entry.getObjectId()),
3638
dtype_(entry.getDtype()),
3739
initialMode_(entry.getInitialMode()),
38-
isRestricted_(entry.isRestricted()) {}
40+
aclRootState_(entry.aclRootState()) {}
3941

4042
UnmaterializedUnloadedBlobDirEntry(
4143
const UnmaterializedUnloadedBlobDirEntry&) = default;
@@ -67,14 +69,18 @@ class UnmaterializedUnloadedBlobDirEntry {
6769
}
6870

6971
bool isRestricted() const {
70-
return isRestricted_;
72+
return aclRootState_ == AclRootState::RestrictedAclRoot;
73+
}
74+
75+
std::optional<bool> hasACL() const {
76+
return hasACLFromAclRootState(aclRootState_);
7177
}
7278

7379
private:
7480
ObjectId objectId_;
7581
dtype_t dtype_;
7682
mode_t initialMode_;
77-
bool isRestricted_ = false;
83+
AclRootState aclRootState_{AclRootState::Unknown};
7884
};
7985

8086
} // namespace facebook::eden

0 commit comments

Comments
 (0)