aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-05-24 20:09:26 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-05-24 20:09:26 -0500
commit2f2554e1f4236acf808ea758ab0d0cf4d298b9ee (patch)
tree715ed1e55f82b16c1908d08af1faa4b5eb3af1b4 /src
parent7ebbf051bbafcb85f0d763646d7ca5d91cafdcb2 (diff)
vfs: bypass userspace lookup cache
Diffstat (limited to 'src')
-rw-r--r--src/src/vfs/mo2filesystem.cpp72
1 files changed, 7 insertions, 65 deletions
diff --git a/src/src/vfs/mo2filesystem.cpp b/src/src/vfs/mo2filesystem.cpp
index 647bce6..013fff5 100644
--- a/src/src/vfs/mo2filesystem.cpp
+++ b/src/src/vfs/mo2filesystem.cpp
@@ -232,34 +232,8 @@ void invalidateDirCache(Mo2FsContext* ctx, const std::string& dirPath)
// need to remove all entries with the given parent inode.
void invalidateLookupCache(Mo2FsContext* ctx, const std::string& dirPath)
{
- if (ctx == nullptr) {
- return;
- }
-
- std::vector<fuse_ino_t> parentsToClear;
- {
- std::shared_lock inodeLock(ctx->inode_mutex);
- std::scoped_lock lookupLock(ctx->lookup_cache_mutex);
- for (const auto& [parentIno, _] : ctx->lookup_cache_by_parent) {
- const std::string parentPath =
- parentIno == 1 ? std::string{} : ctx->inodes->getPath(parentIno);
- if (parentIno == 1 || pathTouchesMutation(parentPath, dirPath)) {
- parentsToClear.push_back(parentIno);
- }
- }
- }
-
- std::scoped_lock lock(ctx->lookup_cache_mutex);
- for (const fuse_ino_t parentIno : parentsToClear) {
- auto idxIt = ctx->lookup_cache_by_parent.find(parentIno);
- if (idxIt == ctx->lookup_cache_by_parent.end()) {
- continue;
- }
- for (const auto& childName : idxIt->second) {
- ctx->lookup_cache.erase({parentIno, childName});
- }
- ctx->lookup_cache_by_parent.erase(idxIt);
- }
+ (void)ctx;
+ (void)dirPath;
}
bool isStrictDescendantPath(const std::string& path, const std::string& parent)
@@ -1020,23 +994,10 @@ void mo2_lookup(fuse_req_t req, fuse_ino_t parent, const char* name)
ctx->lookup_count.fetch_add(1, std::memory_order_relaxed);
maybeLogCounters(ctx);
- // Fast path: check userspace lookup cache. The kernel FUSE dcache is
- // case-sensitive, so Wine's different-case probes ("Shaders", "shaders")
- // each miss the kernel cache and reach us. Our cache keys on normalized
- // (lowercased) name so all case variants hit on the second probe.
- const std::string normName = normalizeForLookup(name);
- const auto cacheKey = std::make_pair(parent, normName);
- {
- std::scoped_lock lock(ctx->lookup_cache_mutex);
- auto it = ctx->lookup_cache.find(cacheKey);
- if (it != ctx->lookup_cache.end()) {
- // Cache hit — reply directly, no tree/inode locks needed
- fuse_reply_entry(req, &it->second.entry);
- return;
- }
- }
-
- // Cache miss — do the full lookup
+ // Do the full lookup every time. The userspace lookup cache was a
+ // performance shortcut, but crash reports showed corruption while updating
+ // its reverse index under concurrent Proton startup probes. Kernel FUSE
+ // dcache still handles repeated exact-case lookups.
const auto lr = lookupChild(ctx, parent, name);
if (!lr.found) {
@@ -1046,16 +1007,6 @@ void mo2_lookup(fuse_req_t req, fuse_ino_t parent, const char* name)
e.attr_timeout = NEGATIVE_TTL_SECONDS;
e.entry_timeout = NEGATIVE_TTL_SECONDS;
- // Cache negative results too (Wine probes many non-existent paths)
- {
- std::scoped_lock lock(ctx->lookup_cache_mutex);
- Mo2FsContext::LookupCacheEntry lce;
- lce.child_ino = 0;
- lce.entry = e;
- ctx->lookup_cache[cacheKey] = lce;
- ctx->lookup_cache_by_parent[cacheKey.first].push_back(cacheKey.second);
- }
-
fuse_reply_entry(req, &e);
return;
}
@@ -1094,7 +1045,7 @@ void mo2_lookup(fuse_req_t req, fuse_ino_t parent, const char* name)
}
}
- // Build the entry_param and cache it for future case-variant lookups
+ // Build the entry_param for the kernel dcache.
struct fuse_entry_param e;
std::memset(&e, 0, sizeof(e));
e.ino = childIno;
@@ -1107,15 +1058,6 @@ void mo2_lookup(fuse_req_t req, fuse_ino_t parent, const char* name)
lr.snap.real_path);
}
- {
- std::scoped_lock lock(ctx->lookup_cache_mutex);
- Mo2FsContext::LookupCacheEntry lce;
- lce.child_ino = childIno;
- lce.entry = e;
- ctx->lookup_cache[cacheKey] = lce;
- ctx->lookup_cache_by_parent[cacheKey.first].push_back(cacheKey.second);
- }
-
fuse_reply_entry(req, &e);
}