summaryrefslogtreecommitdiff
path: root/jni/FuseDaemon.cpp
diff options
context:
space:
mode:
author Zim <zezeozue@google.com> 2020-02-19 01:23:26 +0000
committer Zim <zezeozue@google.com> 2020-02-19 11:07:43 +0000
commita76c349ea76a43d5bb7e4d889bb43cccf72371fc (patch)
treec41e7ba6cf889522d76c6abf61f4bb439580b583 /jni/FuseDaemon.cpp
parentdab62a2b9b915d78752f925fda06eefa5f2d81c4 (diff)
Invalidate FUSE VFS dentry cache
To improve filesystem performance we can reduce unnecessary requests to the FUSE daemon by enabling VFS caching of dentries after a FUSE_LOOKUP request. To enable correctly, we should ensure that the lower filesystem dentries are not modified outside of the FUSE driver. Unfortunately, we already do this when handling IO requests over binder using the ContentResolver interface. To fix, we should invalidate any FUSE dentries in the VFS cache so that subsequent lookups for those files do not return incorrectly cached values from the VFS. This change just adds support for invalidating FUSE VFS cache dentries, subsequent cl will call it when required. Note that it should never be called in the execution path of a related filesytem operation. See fuse_lowlevel.h for more details. Will ensure that this is never called in the FUSE execution path in a follow up Test: atest FuseDaemonHostTest#testVfsCacheConsistency Bug: 145741152 Change-Id: I54e67f63a29c82a392916fb28d1a7f8f894c685b
Diffstat (limited to 'jni/FuseDaemon.cpp')
-rw-r--r--jni/FuseDaemon.cpp27
1 files changed, 27 insertions, 0 deletions
diff --git a/jni/FuseDaemon.cpp b/jni/FuseDaemon.cpp
index 282a08834..d8c2f46be 100644
--- a/jni/FuseDaemon.cpp
+++ b/jni/FuseDaemon.cpp
@@ -299,6 +299,7 @@ struct fuse {
std::recursive_mutex lock;
const string path;
node* const root;
+ struct fuse_session* se;
/*
* Used to make JNI calls to MediaProvider.
@@ -1540,6 +1541,31 @@ bool FuseDaemon::ShouldOpenWithFuse(int fd, bool for_read, const std::string& pa
return use_fuse;
}
+void FuseDaemon::InvalidateFuseDentryCache(const std::string& path) {
+ TRACE_VERBOSE << "Invalidating dentry for path " << path;
+
+ if (active.load(std::memory_order_acquire)) {
+ string name;
+ fuse_ino_t parent;
+
+ {
+ std::lock_guard<std::recursive_mutex> guard(fuse->lock);
+ const node* node = node::LookupAbsolutePath(fuse->root, path);
+ if (node) {
+ name = node->GetName();
+ parent = fuse->ToInode(node->GetParent());
+ }
+ }
+
+ if (!name.empty() &&
+ fuse_lowlevel_notify_inval_entry(fuse->se, parent, name.c_str(), name.size())) {
+ LOG(ERROR) << "Failed to invalidate dentry for path " << path;
+ }
+ } else {
+ TRACE << "FUSE daemon is inactive. Cannot invalidate dentry for " << path;
+ }
+}
+
FuseDaemon::FuseDaemon(JNIEnv* env, jobject mediaProvider) : mp(env, mediaProvider),
active(false), fuse(nullptr) {}
@@ -1594,6 +1620,7 @@ void FuseDaemon::Start(const int fd, const std::string& path) {
PLOG(ERROR) << "Failed to create session ";
return;
}
+ fuse_default.se = se;
se->fd = fd;
se->mountpoint = strdup(path.c_str());