summaryrefslogtreecommitdiff
path: root/fs/fuse/dir.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-18 16:55:52 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-18 16:55:52 +0200
commit93467b31bec6da512b51544e5e4584f2745e995e (patch)
tree2ea2be38c5e4dc9aafffbbc0db5aae0f6513a1d9 /fs/fuse/dir.c
parent8ca1f4c6fb1462ee120730ea75c19da10d2f2d6f (diff)
parent7a5cef0db4795d9d453a12e0f61b5b7634fc4d40 (diff)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r--fs/fuse/dir.c36
1 files changed, 15 insertions, 21 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index b658b6baf72f..97751bacb79c 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1587,40 +1587,34 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
{
int err = -ENOTDIR;
struct inode *parent;
- struct dentry *dir = NULL;
- struct dentry *entry = NULL;
+ struct dentry *dir;
+ struct dentry *entry;
parent = fuse_ilookup(fc, parent_nodeid, NULL);
if (!parent)
return -ENOENT;
+ inode_lock_nested(parent, I_MUTEX_PARENT);
if (!S_ISDIR(parent->i_mode))
- goto put_parent;
+ goto unlock;
err = -ENOENT;
dir = d_find_alias(parent);
if (!dir)
- goto put_parent;
- while (!entry) {
- struct dentry *child = try_lookup_noperm(name, dir);
- if (!child || IS_ERR(child))
- goto put_parent;
- entry = start_removing_dentry(dir, child);
- dput(child);
- if (IS_ERR(entry))
- goto put_parent;
- if (!d_same_name(entry, dir, name)) {
- end_removing(entry);
- entry = NULL;
- }
- }
+ goto unlock;
+
+ name->hash = full_name_hash(dir, name->name, name->len);
+ entry = d_lookup(dir, name);
+ dput(dir);
+ if (!entry)
+ goto unlock;
fuse_dir_changed(parent);
if (!(flags & FUSE_EXPIRE_ONLY))
d_invalidate(entry);
fuse_invalidate_entry_cache(entry);
- if (child_nodeid != 0) {
+ 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;
@@ -1648,10 +1642,10 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
} else {
err = 0;
}
+ dput(entry);
- end_removing(entry);
- put_parent:
- dput(dir);
+ unlock:
+ inode_unlock(parent);
iput(parent);
return err;
}