linux/fs/fuse
Zhang Tianci 69eb56f69e fuse: check attributes staleness on fuse_iget()
Function fuse_direntplus_link() might call fuse_iget() to initialize a new
fuse_inode and change its attributes. If fi->attr_version is always
initialized with 0, even if the attributes returned by the FUSE_READDIR
request is staled, as the new fi->attr_version is 0, fuse_change_attributes
will still set the staled attributes to inode. This wrong behaviour may
cause file size inconsistency even when there is no changes from
server-side.

To reproduce the issue, consider the following 2 programs (A and B) are
running concurrently,

        A                                               B
----------------------------------      --------------------------------
{ /fusemnt/dir/f is a file path in a fuse mount, the size of f is 0. }

readdir(/fusemnt/dir) start
//Daemon set size 0 to f direntry
                                        fallocate(f, 1024)
                                        stat(f) // B see size 1024
                                        echo 2 > /proc/sys/vm/drop_caches
readdir(/fusemnt/dir) reply to kernel
Kernel set 0 to the I_NEW inode

                                        stat(f) // B see size 0

In the above case, only program B is modifying the file size, however, B
observes file size changing between the 2 'readonly' stat() calls. To fix
this issue, we should make sure readdirplus still follows the rule of
attr_version staleness checking even if the fi->attr_version is lost due to
inode eviction.

To identify this situation, the new fc->evict_ctr is used to record whether
the eviction of inodes occurs during the readdirplus request processing.
If it does, the result of readdirplus may be inaccurate; otherwise, the
result of readdirplus can be trusted. Although this may still lead to
incorrect invalidation, considering the relatively low frequency of
evict occurrences, it should be acceptable.

Link: https://lore.kernel.org/lkml/20230711043405.66256-2-zhangjiachen.jaycee@bytedance.com/
Link: https://lore.kernel.org/lkml/20241114070905.48901-1-zhangtianci.1997@bytedance.com/

Reported-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
Suggested-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Zhang Tianci <zhangtianci.1997@bytedance.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2024-11-18 12:24:13 +01:00
..
acl.c fuse: support idmapped ->set_acl 2024-09-04 16:51:11 +02:00
control.c [tree-wide] finally take no_llseek out 2024-09-27 08:18:43 -07:00
cuse.c fuse: remove pages for requests and exclusively use folios 2024-11-05 14:08:35 +01:00
dax.c fs/fuse: introduce and use fuse_simple_idmap_request() helper 2024-09-23 11:07:55 +02:00
dev.c fuse: remove pages for requests and exclusively use folios 2024-11-05 14:08:35 +01:00
dir.c fuse: check attributes staleness on fuse_iget() 2024-11-18 12:24:13 +01:00
file.c fuse: remove pages for requests and exclusively use folios 2024-11-05 14:08:35 +01:00
fuse_i.h fuse: check attributes staleness on fuse_iget() 2024-11-18 12:24:13 +01:00
fuse_trace.h fuse: add simple request tracepoints 2024-08-29 11:43:13 +02:00
inode.c fuse: check attributes staleness on fuse_iget() 2024-11-18 12:24:13 +01:00
ioctl.c fuse: remove pages for requests and exclusively use folios 2024-11-05 14:08:35 +01:00
iomode.c fuse: fix parallel dio write on file open in passthrough mode 2024-04-15 10:12:44 +02:00
Kconfig fuse: introduce FUSE_PASSTHROUGH capability 2024-02-23 17:36:32 +01:00
Makefile fuse: enable dynamic configuration of fuse max pages limit (FUSE_MAX_MAX_PAGES) 2024-10-25 17:05:49 +02:00
passthrough.c fuse: remove stray debug line 2024-10-25 17:05:49 +02:00
readdir.c fuse: check attributes staleness on fuse_iget() 2024-11-18 12:24:13 +01:00
sysctl.c fuse: enable dynamic configuration of fuse max pages limit (FUSE_MAX_MAX_PAGES) 2024-10-25 17:05:49 +02:00
virtio_fs.c fuse: remove pages for requests and exclusively use folios 2024-11-05 14:08:35 +01:00
xattr.c fs/fuse: introduce and use fuse_simple_idmap_request() helper 2024-09-23 11:07:55 +02:00