diff options
author | Jiachen Zhang <zhangjiachen.jaycee@bytedance.com> | 2023-07-11 12:34:02 +0800 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2023-08-21 12:14:59 +0200 |
commit | 7d875e66859a4359acd29ce0d188e1aff048e7ed (patch) | |
tree | 5aee54823ebc695b43e1ee17a98ed1e887264c54 /fs/fuse/dir.c | |
parent | 972f4c46d0a1bb7fde3ce0bd15775855b2d02c68 (diff) | |
download | linux-stable-7d875e66859a4359acd29ce0d188e1aff048e7ed.tar.gz linux-stable-7d875e66859a4359acd29ce0d188e1aff048e7ed.tar.bz2 linux-stable-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/dir.c')
-rw-r--r-- | fs/fuse/dir.c | 11 |
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 |