feat: add V2/INVALIDATE_PATH socket message for cache invalidation - #48
feat: add V2/INVALIDATE_PATH socket message for cache invalidation#48flash7777 wants to merge 2 commits into
Conversation
When a sync daemon (e.g. cloudd) creates new placeholder files in the
underlying filesystem after the FUSE mount is active, the kernel may
cache negative lookups and not show the new files until the user
navigates away and back.
This adds a new socket message that the sync daemon can send to
invalidate a path in the FUSE kernel cache:
V2/INVALIDATE_PATH:{"arguments":{"path":"/subdir"}}
On receiving this message, openvfs calls fuse_invalidate_path() which
clears the kernel's cached entries for that path. The next readdir
or lookup will see the new files.
The fuse instance pointer is captured during init and stored globally
for use by the socket thread.
dragotin
left a comment
There was a problem hiding this comment.
Interesting feature. When I investigated with the help of a machine, it suggested to use file_invalidate_path also from within the codebase, when the SocketThread received info about the hydrated file. Maybe that would fix the problem?
Here are some remarks.
| // Store fuse instance for invalidation from socket thread | ||
| auto *ctx = fuse_get_context(); | ||
| if (ctx) { | ||
| _fuseInstance = ctx->fuse; |
There was a problem hiding this comment.
Can't you completely get rid of the _fuseInstance var by calling fuse_get_context()->fuse ?
| std::string fusePath = path; | ||
| if (!fusePath.empty() && fusePath[0] != '/') { | ||
| fusePath = "/" + fusePath; | ||
| } |
There was a problem hiding this comment.
I think you can use const auto fusePath = getInternalPath(path);
| try { | ||
| const auto j = json::parse(msgAttr); | ||
| const auto path = j["arguments"]["path"].get<string>(); | ||
| cout << "Invalidating path: " << path << endl; |
| cout << "Invalidating path: " << path << endl; | ||
| openvfsfuse_invalidate_path(path); | ||
| } catch (json::exception &e) { | ||
| std::cerr << "Invalid INVALIDATE_PATH message: " << msgAttr << e.what() << std::endl; |
Per review by @dragotin: - Replace _fuseInstance global with fuse_get_context()->fuse - Use getInternalPath() for path normalization in invalidate - Replace cout/cerr with openvfsfuse_log for consistent logging Note: invalidating after hydration completion would require adding the file path to HydJob struct — left as follow-up since HydJob currently only stores state.
dragotin
left a comment
There was a problem hiding this comment.
One more comment. Thanks.
Btw, I think the cache clearing could happen in openVFSfuse_open() after the hydration is finished. There we are in the right thread and have the path available. It is still the same that came in to the function. (I haven't tried...)
| return; | ||
| } | ||
| const auto fusePath = getInternalPath(path); | ||
| std::string fuseStr = "/" + fusePath.string(); |
There was a problem hiding this comment.
Could you please put that behind a function getFusePath() similar to the other two? That way we can properly document the difference between the three pathes.
Summary
When a sync daemon creates new placeholder files in the underlying filesystem after the FUSE mount is active, the kernel may cache negative lookups. New files don't appear in directory listings until the user navigates away and back.
This adds a new socket message that the sync daemon can send to invalidate a path in the FUSE kernel cache:
On receiving this message, openvfs calls
fuse_invalidate_path()which clears the kernel's cached entries for that path. The nextreaddirorlookupwill see the new files.Use case
Headless sync daemons like cloudd periodically sync remote directory listings and create local placeholder files. Without cache invalidation, Nautilus and other file managers don't show new files until manual refresh.
Changes
openvfsfuse.cpp: storefuse *pointer during init, addopenvfsfuse_invalidate_path()openvfsfuse.h: declareopenvfsfuse_invalidate_path()socketthread.cpp: handleV2/INVALIDATE_PATHmessage, call invalidate3 files, +37 lines.
Test plan