Message ID | 20210514015517.258-1-changfengnan@vivo.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fuse: fix inconsistent status between faccess and mkdir | expand |
On Fri, May 14, 2021 at 09:55:17AM +0800, Fengnan Chang wrote: > +++ b/fs/fuse/dir.c > @@ -1065,6 +1065,14 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, > fuse_fillattr(inode, &outarg.attr, stat); > } > } > + if (err == -ENOENT) { > + struct dentry *entry; > + > + entry = d_obtain_alias(inode); Why d_obtain_alias() instead of d_find_any_alias()? And what if you find the wrong alias? ie an inode with two links? Or does fuse not support hardlinks?
we should us d_find_any_alias() rather than d_obtain_alias(), it's my mistake. Fuse is support hardlinks, if an inode with two links, we may found wrong alias, we may need invalidate all dentry, because of the file is not exist anymore. But in other kernel code, I didn't see any handling for this situation. I can't figure out why. Thanks. -----邮件原件----- 发件人: Matthew Wilcox <willy@infradead.org> 发送时间: 2021年5月14日 10:27 收件人: Fengnan Chang <changfengnan@vivo.com> 抄送: miklos@szeredi.hu; linux-fsdevel@vger.kernel.org 主题: Re: [PATCH] fuse: fix inconsistent status between faccess and mkdir On Fri, May 14, 2021 at 09:55:17AM +0800, Fengnan Chang wrote: > +++ b/fs/fuse/dir.c > @@ -1065,6 +1065,14 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, > fuse_fillattr(inode, &outarg.attr, stat); > } > } > + if (err == -ENOENT) { > + struct dentry *entry; > + > + entry = d_obtain_alias(inode); Why d_obtain_alias() instead of d_find_any_alias()? And what if you find the wrong alias? ie an inode with two links? Or does fuse not support hardlinks?
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 06a18700a845..154dd4578762 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1065,6 +1065,14 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, fuse_fillattr(inode, &outarg.attr, stat); } } + if (err == -ENOENT) { + struct dentry *entry; + + entry = d_obtain_alias(inode); + if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) + fuse_invalidate_entry_cache(entry); + } + return err; } @@ -1226,6 +1234,14 @@ static int fuse_access(struct inode *inode, int mask) fm->fc->no_access = 1; err = 0; } + if (err == -ENOENT) { + struct dentry *entry; + + entry = d_obtain_alias(inode); + if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) + fuse_invalidate_entry_cache(entry); + } + return err; }
since FUSE caches dentries and attributes with separate timeout, It may happen that checking the permission returns -ENOENT, but because the dentries cache has not timed out, creating the file returns -EEXIST. Fix this by when return ENOENT, mark the entry as stale. Signed-off-by: Fengnan Chang <changfengnan@vivo.com> --- fs/fuse/dir.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)