All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] fuse: update size attr before doing IO
@ 2024-03-07 15:08 Sweet Tea Dorminy
  2024-03-07 16:09 ` Josef Bacik
  2024-03-11 10:01 ` Miklos Szeredi
  0 siblings, 2 replies; 8+ messages in thread
From: Sweet Tea Dorminy @ 2024-03-07 15:08 UTC (permalink / raw)
  To: miklos, linux-fsdevel, kernel-team, josef, amir73il; +Cc: Sweet Tea Dorminy

All calls into generic vfs functions need to make sure that the inode
attributes used by those functions are up to date, by calling
fuse_update_attributes() as appropriate.

generic_write_checks() accesses inode size in order to get the
appropriate file offset for files opened with O_APPEND. Currently, in
some cases, fuse_update_attributes() is not called before
generic_write_checks(), potentially resulting in corruption/overwrite of
previously appended data if i_size is out of date in the cached inode.

Therefore,  make sure fuse_update_attributes() is always
called before generic_write_checks(), and add a note about why it's not
necessary for some llseek calls.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 fs/fuse/file.c | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 1b0b9f2a4fbf..d69b2dd0168c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1408,13 +1408,16 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
 	ssize_t err, count;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 
-	if (fc->writeback_cache) {
-		/* Update size (EOF optimization) and mode (SUID clearing) */
-		err = fuse_update_attributes(mapping->host, file,
-					     STATX_SIZE | STATX_MODE);
-		if (err)
-			return err;
+	/*
+	 * Update size (EOF optimization, and O_APPEND correctness) and
+	 * mode (SUID clearing)
+	 */
+	err = fuse_update_attributes(mapping->host, file,
+				     STATX_SIZE | STATX_MODE);
+	if (err)
+		return err;
 
+	if (fc->writeback_cache) {
 		if (fc->handle_killpriv_v2 &&
 		    setattr_should_drop_suidgid(&nop_mnt_idmap,
 						file_inode(file))) {
@@ -1666,10 +1669,19 @@ static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
 
 static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
-	struct inode *inode = file_inode(iocb->ki_filp);
+	struct file *file = iocb->ki_filp;
+	struct inode *inode = file_inode(file);
 	struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
 	ssize_t res;
 	bool exclusive;
+	/*
+	 * For O_APPEND files, we need to make sure the size is right before
+	 * generic_write_checks() grabs it.
+	 */
+	res = fuse_update_attributes(file->f_mapping->host, file, STATX_SIZE);
+	if (res)
+		return res;
+
 
 	fuse_dio_lock(iocb, from, &exclusive);
 	res = generic_write_checks(iocb, from);
@@ -2815,7 +2827,11 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
 	switch (whence) {
 	case SEEK_SET:
 	case SEEK_CUR:
-		 /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
+		 /*
+		  * No i_mutex protection necessary for SEEK_CUR and SEEK_SET.
+		  * Even if we seek to a point outside the currently known size,
+		  * read and write will update the attributes before doing IO
+		  */
 		retval = generic_file_llseek(file, offset, whence);
 		break;
 	case SEEK_END:

base-commit: cdf6ac2a03d253f05d3e798f60f23dea1b176b92
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-03-14 10:27 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-07 15:08 [PATCH] fuse: update size attr before doing IO Sweet Tea Dorminy
2024-03-07 16:09 ` Josef Bacik
2024-03-07 19:39   ` Bernd Schubert
2024-03-11 10:01 ` Miklos Szeredi
2024-03-12 18:18   ` Sweet Tea Dorminy
2024-03-12 21:55     ` Bernd Schubert
2024-03-12 23:08       ` Sweet Tea Dorminy
2024-03-14 10:26     ` Miklos Szeredi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.