Commit 7d875e66 authored by Jiachen Zhang's avatar Jiachen Zhang Committed by Miklos Szeredi

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: default avatarJiachen Zhang <zhangjiachen.jaycee@bytedance.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 972f4c46
...@@ -749,7 +749,8 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry, ...@@ -749,7 +749,8 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
if (err == -ENOSYS) { if (err == -ENOSYS) {
fc->no_create = 1; fc->no_create = 1;
goto mknod; goto mknod;
} } else if (err == -EEXIST)
fuse_invalidate_entry(entry);
out_dput: out_dput:
dput(res); dput(res);
return err; return err;
...@@ -829,6 +830,8 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args, ...@@ -829,6 +830,8 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
return 0; return 0;
out_put_forget_req: out_put_forget_req:
if (err == -EEXIST)
fuse_invalidate_entry(entry);
kfree(forget); kfree(forget);
return err; return err;
} }
...@@ -980,7 +983,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) ...@@ -980,7 +983,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
if (!err) { if (!err) {
fuse_dir_changed(dir); fuse_dir_changed(dir);
fuse_entry_unlinked(entry); fuse_entry_unlinked(entry);
} else if (err == -EINTR) } else if (err == -EINTR || err == -ENOENT)
fuse_invalidate_entry(entry); fuse_invalidate_entry(entry);
return err; return err;
} }
...@@ -1003,7 +1006,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) ...@@ -1003,7 +1006,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
if (!err) { if (!err) {
fuse_dir_changed(dir); fuse_dir_changed(dir);
fuse_entry_unlinked(entry); fuse_entry_unlinked(entry);
} else if (err == -EINTR) } else if (err == -EINTR || err == -ENOENT)
fuse_invalidate_entry(entry); fuse_invalidate_entry(entry);
return err; return err;
} }
...@@ -1044,7 +1047,7 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, ...@@ -1044,7 +1047,7 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
/* newent will end up negative */ /* newent will end up negative */
if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent))
fuse_entry_unlinked(newent); fuse_entry_unlinked(newent);
} else if (err == -EINTR) { } else if (err == -EINTR || err == -ENOENT) {
/* If request was interrupted, DEITY only knows if the /* If request was interrupted, DEITY only knows if the
rename actually took place. If the invalidation rename actually took place. If the invalidation
fails (e.g. some process has CWD under the renamed fails (e.g. some process has CWD under the renamed
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment