summaryrefslogtreecommitdiff
path: root/jni/FuseDaemon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'jni/FuseDaemon.cpp')
-rwxr-xr-xjni/FuseDaemon.cpp47
1 files changed, 20 insertions, 27 deletions
diff --git a/jni/FuseDaemon.cpp b/jni/FuseDaemon.cpp
index a75660c11..b30cffa15 100755
--- a/jni/FuseDaemon.cpp
+++ b/jni/FuseDaemon.cpp
@@ -390,12 +390,14 @@ static void fuse_inval(fuse_session* se, fuse_ino_t parent_ino, fuse_ino_t child
}
}
-static double get_attr_timeout(const string& path, bool should_inval, node* node,
- struct fuse* fuse) {
- if (fuse->disable_dentry_cache || should_inval || is_package_owned_path(path, fuse->path)) {
+static double get_attr_timeout(const string& path, node* node, struct fuse* fuse) {
+ if (fuse->disable_dentry_cache || node->ShouldInvalidate() ||
+ is_package_owned_path(path, fuse->path)) {
// We set dentry timeout to 0 for the following reasons:
// 1. The dentry cache was completely disabled
- // 2. Case-insensitive lookups need to invalidate other case-insensitive dentry matches
+ // 2.1 Case-insensitive lookups need to invalidate other case-insensitive dentry matches
+ // 2.2 Nodes supporting transforms need to be invalidated, so that subsequent lookups by a
+ // uid requiring a transform is guaranteed to come to the FUSE daemon.
// 3. With app data isolation enabled, app A should not guess existence of app B from the
// Android/{data,obb}/<package> paths, hence we prevent the kernel from caching that
// information.
@@ -404,8 +406,7 @@ static double get_attr_timeout(const string& path, bool should_inval, node* node
return std::numeric_limits<double>::max();
}
-static double get_entry_timeout(const string& path, bool should_inval, node* node,
- struct fuse* fuse) {
+static double get_entry_timeout(const string& path, node* node, struct fuse* fuse) {
string media_path = fuse->GetEffectiveRootPath() + "/Android/media";
if (path.find(media_path, 0) == 0) {
// Installd might delete Android/media/<package> dirs when app data is cleared.
@@ -413,7 +414,7 @@ static double get_entry_timeout(const string& path, bool should_inval, node* nod
// dir via FUSE.
return 0;
}
- return get_attr_timeout(path, should_inval, node, fuse);
+ return get_attr_timeout(path, node, fuse);
}
static std::string get_path(node* node) {
@@ -433,7 +434,7 @@ static node* make_node_entry(fuse_req_t req, node* parent, const string& name, c
return NULL;
}
- bool should_inval = false;
+ bool should_invalidate = false;
bool transforms_complete = true;
int transforms = 0;
string io_path;
@@ -441,7 +442,7 @@ static node* make_node_entry(fuse_req_t req, node* parent, const string& name, c
if (S_ISREG(e->attr.st_mode)) {
// Handle potential file transforms
std::unique_ptr<mediaprovider::fuse::FileLookupResult> file_lookup_result =
- fuse->mp->FileLookup(path, req->ctx.uid);
+ fuse->mp->FileLookup(path, req->ctx.uid, req->ctx.pid);
if (!file_lookup_result) {
// Fail lookup if we can't fetch FileLookupResult for path
@@ -453,37 +454,34 @@ static node* make_node_entry(fuse_req_t req, node* parent, const string& name, c
transforms = file_lookup_result->transforms;
io_path = file_lookup_result->io_path;
transforms_complete = file_lookup_result->transforms_complete;
+ // Invalidate if the inode supports transforms so that we always get a lookup into userspace
+ should_invalidate = file_lookup_result->transforms_supported;
// Update size with io_path size if io_path is not same as path
if (!io_path.empty() && (io_path != path) && (lstat(io_path.c_str(), &e->attr) < 0)) {
*error_code = errno;
return NULL;
}
-
- // Invalidate if there are any transforms so that we always get a lookup into userspace
- should_inval = should_inval || transforms;
}
node = parent->LookupChildByName(name, true /* acquire */, transforms);
if (!node) {
- node = ::node::Create(parent, name, io_path, transforms_complete, transforms, &fuse->lock,
- &fuse->tracker);
+ node = ::node::Create(parent, name, io_path, should_invalidate, transforms_complete,
+ transforms, &fuse->lock, &fuse->tracker);
} else if (!mediaprovider::fuse::containsMount(path, std::to_string(getuid() / PER_USER_RANGE))) {
- should_inval = should_inval || node->HasCaseInsensitiveMatch();
// Only invalidate a path if it does not contain mount.
// Invalidate both names to ensure there's no dentry left in the kernel after the following
// operations:
// 1) touch foo, touch FOO, unlink *foo*
// 2) touch foo, touch FOO, unlink *FOO*
// Invalidating lookup_name fixes (1) and invalidating node_name fixes (2)
- // |should_inval| invalidates lookup_name by using 0 timeout below and we explicitly
+ // SetShouldInvalidate invalidates lookup_name by using 0 timeout below and we explicitly
// invalidate node_name if different case
// Note that we invalidate async otherwise we will deadlock the kernel
if (name != node->GetName()) {
- should_inval = true;
// Record that we have made a case insensitive lookup, this allows us invalidate nodes
// correctly on subsequent lookups for the case of |node|
- node->SetCaseInsensitiveMatch();
+ node->SetShouldInvalidate();
// Make copies of the node name and path so we're not attempting to acquire
// any node locks from the invalidation thread. Depending on timing, we may end
@@ -503,8 +501,8 @@ static node* make_node_entry(fuse_req_t req, node* parent, const string& name, c
// reuse inode numbers.
e->generation = 0;
e->ino = fuse->ToInode(node);
- e->entry_timeout = get_entry_timeout(path, should_inval, node, fuse);
- e->attr_timeout = get_attr_timeout(path, should_inval, node, fuse);
+ e->entry_timeout = get_entry_timeout(path, node, fuse);
+ e->attr_timeout = get_attr_timeout(path, node, fuse);
return node;
}
@@ -693,10 +691,7 @@ static void pf_getattr(fuse_req_t req,
if (lstat(path.c_str(), &s) < 0) {
fuse_reply_err(req, errno);
} else {
- fuse_reply_attr(
- req, &s,
- get_attr_timeout(path, node->GetTransforms() || node->HasCaseInsensitiveMatch(),
- node, fuse));
+ fuse_reply_attr(req, &s, get_attr_timeout(path, node, fuse));
}
}
@@ -791,9 +786,7 @@ static void pf_setattr(fuse_req_t req,
}
lstat(path.c_str(), attr);
- fuse_reply_attr(req, attr,
- get_attr_timeout(path, node->GetTransforms() || node->HasCaseInsensitiveMatch(),
- node, fuse));
+ fuse_reply_attr(req, attr, get_attr_timeout(path, node, fuse));
}
static void pf_canonical_path(fuse_req_t req, fuse_ino_t ino)