summaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorJiachen Zhang <zhangjiachen.jaycee@bytedance.com>2023-07-11 06:34:02 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2023-08-21 12:14:59 +0200
commit7d875e66859a4359acd29ce0d188e1aff048e7ed (patch)
tree5aee54823ebc695b43e1ee17a98ed1e887264c54 /fs/fuse
parentfuse: cache btime (diff)
downloadlinux-7d875e66859a4359acd29ce0d188e1aff048e7ed.tar.xz
linux-7d875e66859a4359acd29ce0d188e1aff048e7ed.zip
fuse: invalidate dentry on EEXIST creates or ENOENT deletes
The EEXIST errors returned from server are strong sign that a local negative dentry should be invalidated. Similarly, The ENOENT errors from server can also be a sign of revalidate failure. This commit invalidates dentries on EEXIST creates and ENOENT deletes by calling fuse_invalidate_entry(), which improves the consistency with no performance degradation. Signed-off-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 3db9d26d341e..e190d09f220d 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -749,7 +749,8 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
if (err == -ENOSYS) {
fc->no_create = 1;
goto mknod;
- }
+ } else if (err == -EEXIST)
+ fuse_invalidate_entry(entry);
out_dput:
dput(res);
return err;
@@ -829,6 +830,8 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
return 0;
out_put_forget_req:
+ if (err == -EEXIST)
+ fuse_invalidate_entry(entry);
kfree(forget);
return err;
}
@@ -980,7 +983,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
if (!err) {
fuse_dir_changed(dir);
fuse_entry_unlinked(entry);
- } else if (err == -EINTR)
+ } else if (err == -EINTR || err == -ENOENT)
fuse_invalidate_entry(entry);
return err;
}
@@ -1003,7 +1006,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
if (!err) {
fuse_dir_changed(dir);
fuse_entry_unlinked(entry);
- } else if (err == -EINTR)
+ } else if (err == -EINTR || err == -ENOENT)
fuse_invalidate_entry(entry);
return err;
}
@@ -1044,7 +1047,7 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
/* newent will end up negative */
if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent))
fuse_entry_unlinked(newent);
- } else if (err == -EINTR) {
+ } else if (err == -EINTR || err == -ENOENT) {
/* If request was interrupted, DEITY only knows if the
rename actually took place. If the invalidation
fails (e.g. some process has CWD under the renamed