Re: [PATCH] fuse: fix conversion of fuse_reverse_inval_entry() to start_removing()
Miklos Szeredi <[email protected]>
| Newsgroups | org.kernel.vger.ecryptfs,dev.linux.lists.netfs,org.kernel.vger.linux-cifs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-nfs,org.kernel.vger.linux-security-module,org.kernel.vger.linux-unionfs,org.kernel.vger.linux-xfs,org.kernel.vger.selinux |
|---|---|
| Message-ID | <CAJfpegs+o01jgY76WsGnk9j41LS5V0JQSk--d6xsJJp4VjTh8Q@mail.gmail.com> |
On Mon, 1 Dec 2025 at 09:33, Al Viro <[email protected]> wrote: > > On Mon, Dec 01, 2025 at 09:22:54AM +0100, Amir Goldstein wrote: > > > I don't think there is a point in optimizing parallel dir operations > > with FUSE server cache invalidation, but maybe I am missing > > something. > > The interesting part is the expected semantics of operation; > d_invalidate() side definitely doesn't need any of that cruft, > but I would really like to understand what that function > is supposed to do. > > Miklos, could you post a brain dump on that? This function is supposed to invalidate a dentry due to remote changes (FUSE_NOTIFY_INVAL_ENTRY). Originally it was supplied a parent ID and a name and called d_invalidate() on the looked up dentry. Then it grew a variant (FUSE_NOTIFY_DELETE) that was also supplied a child ID, which was matched against the looked up inode. This was commit 451d0f599934 ("FUSE: Notifying the kernel of deletion."), Apparently this worked around the fact that at that time d_invalidate() returned -EBUSY if the target was still in use and didn't unhash the dentry in that case. That was later changed by commit bafc9b754f75 ("vfs: More precise tests in d_invalidate") to unconditionally unhash the target, which effectively made FUSE_NOTIFY_INVAL_ENTRY and FUSE_NOTIFY_DELETE equivalent and the code in question unnecessary. For the future, we could also introduce FUSE_NOTIFY_MOVE, that would differentiate between a delete and a move, while FUSE_NOTIFY_INVAL_ENTRY would continue to be the common (deleted or moved) notification. Attaching untested patch to remove this cruft. Thanks, Miklos
fuse-notify_inval_entry-and-notify_delete-are-equivalent.patch
(text/x-patch, 1022 B)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index ecaec0fea3a1..d9dffc326a26 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1417,34 +1417,9 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
d_invalidate(entry);
fuse_invalidate_entry_cache(entry);
- if (child_nodeid != 0 && d_really_is_positive(entry)) {
- inode_lock(d_inode(entry));
- if (get_node_id(d_inode(entry)) != child_nodeid) {
- err = -ENOENT;
- goto badentry;
- }
- if (d_mountpoint(entry)) {
- err = -EBUSY;
- goto badentry;
- }
- if (d_is_dir(entry)) {
- shrink_dcache_parent(entry);
- if (!simple_empty(entry)) {
- err = -ENOTEMPTY;
- goto badentry;
- }
- d_inode(entry)->i_flags |= S_DEAD;
- }
- dont_mount(entry);
- clear_nlink(d_inode(entry));
- err = 0;
- badentry:
- inode_unlock(d_inode(entry));
- if (!err)
- d_delete(entry);
- } else {
- err = 0;
- }
+ err = 0;
+ if (child_nodeid != 0 && get_node_id(d_inode(entry)) != child_nodeid)
+ err = -ENOENT;
dput(entry);
unlock: