[PATCH] fuse: update inode size after extending passthrough write

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



yangyun reported that libfuse test test_copy_file_range() copies zero
bytes from a newly written file when fuse passthrough is enabled.

The reason is that extending passthrough write is not updating the fuse
inode size and when vfs_copy_file_range() observes a zero size inode,
it returns without calling the filesystem copy_file_range() method.

Extend the fuse inode size to the size of the backing inode after every
passthrough write if the backing inode size is larger.

This does not yet provide cache coherency of fuse inode attributes and
backing inode attributes, but it should prevent situations where fuse
inode size is too small, causing read/copy to be wrongly shortened.

Reported-by: yangyun <yangyun50@xxxxxxxxxx>
Closes: https://github.com/libfuse/libfuse/issues/1048
Fixes: 57e1176e6086 ("fuse: implement read/write passthrough")
Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
---

Doh! force of habbit - fixed subject s/ovl/fuse

Thanks,
Amir.

 fs/fuse/passthrough.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c
index ba3207f6c4ce..d3047a4bc40e 100644
--- a/fs/fuse/passthrough.c
+++ b/fs/fuse/passthrough.c
@@ -20,9 +20,18 @@ static void fuse_file_accessed(struct file *file)
 
 static void fuse_file_modified(struct file *file)
 {
+	struct fuse_file *ff = file->private_data;
+	struct file *backing_file = fuse_file_passthrough(ff);
 	struct inode *inode = file_inode(file);
-
-	fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE);
+	loff_t size = i_size_read(file_inode(backing_file));
+
+	/*
+	 * Most of the time we will be holding inode_lock(), but even if we are
+	 * called from async io completion without inode_lock(), the last write
+	 * will update fuse inode size to the size of the backing inode, even if
+	 * the last write was not the extending write.
+	 */
+	fuse_write_update_attr(inode, size, size);
 }
 
 ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *iter)
-- 
2.34.1





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux