Patch "cifs: Fix FALLOC_FL_ZERO_RANGE to preflush buffered part of target region" has been added to the 6.10-stable tree

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

 



This is a note to let you know that I've just added the patch titled

    cifs: Fix FALLOC_FL_ZERO_RANGE to preflush buffered part of target region

to the 6.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     cifs-fix-falloc_fl_zero_range-to-preflush-buffered-p.patch
and it can be found in the queue-6.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 175ed474961329eb835de3fc7f06f20cf61ee38b
Author: David Howells <dhowells@xxxxxxxxxx>
Date:   Wed Aug 28 21:08:25 2024 +0100

    cifs: Fix FALLOC_FL_ZERO_RANGE to preflush buffered part of target region
    
    [ Upstream commit 91d1dfae464987aaf6c79ff51d8674880fb3be77 ]
    
    Under certain conditions, the range to be cleared by FALLOC_FL_ZERO_RANGE
    may only be buffered locally and not yet have been flushed to the server.
    For example:
    
            xfs_io -f -t -c "pwrite -S 0x41 0 4k" \
                         -c "pwrite -S 0x42 4k 4k" \
                         -c "fzero 0 4k" \
                         -c "pread -v 0 8k" /xfstest.test/foo
    
    will write two 4KiB blocks of data, which get buffered in the pagecache,
    and then fallocate() is used to clear the first 4KiB block on the server -
    but we don't flush the data first, which means the EOF position on the
    server is wrong, and so the FSCTL_SET_ZERO_DATA RPC fails (and xfs_io
    ignores the error), but then when we try to read it, we see the old data.
    
    Fix this by preflushing any part of the target region that above the
    server's idea of the EOF position to force the server to update its EOF
    position.
    
    Note, however, that we don't want to simply expand the file by moving the
    EOF before doing the FSCTL_SET_ZERO_DATA[*] because someone else might see
    the zeroed region or if the RPC fails we then have to try to clean it up or
    risk getting corruption.
    
    [*] And we have to move the EOF first otherwise FSCTL_SET_ZERO_DATA won't
    do what we want.
    
    This fixes the generic/008 xfstest.
    
    [!] Note: A better way to do this might be to split the operation into two
    parts: we only do FSCTL_SET_ZERO_DATA for the part of the range below the
    server's EOF and then, if that worked, invalidate the buffered pages for the
    part above the range.
    
    Fixes: 6b69040247e1 ("cifs/smb3: Fix data inconsistent when zero file range")
    Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
    cc: Steve French <stfrench@xxxxxxxxxxxxx>
    cc: Zhang Xiaoxu <zhangxiaoxu5@xxxxxxxxxx>
    cc: Pavel Shilovsky <pshilov@xxxxxxxxxxxxx>
    cc: Paulo Alcantara <pc@xxxxxxxxxxxxx>
    cc: Shyam Prasad N <nspmangalore@xxxxxxxxx>
    cc: Rohith Surabattula <rohiths.msft@xxxxxxxxx>
    cc: Jeff Layton <jlayton@xxxxxxxxxx>
    cc: linux-cifs@xxxxxxxxxxxxxxx
    cc: linux-mm@xxxxxxxxx
    Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 42352f70b01c..1d6e8eacdd74 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -3219,13 +3219,15 @@ static long smb3_zero_data(struct file *file, struct cifs_tcon *tcon,
 }
 
 static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
-			    loff_t offset, loff_t len, bool keep_size)
+			    unsigned long long offset, unsigned long long len,
+			    bool keep_size)
 {
 	struct cifs_ses *ses = tcon->ses;
 	struct inode *inode = file_inode(file);
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
 	struct cifsFileInfo *cfile = file->private_data;
-	unsigned long long new_size;
+	struct netfs_inode *ictx = netfs_inode(inode);
+	unsigned long long i_size, new_size, remote_size;
 	long rc;
 	unsigned int xid;
 
@@ -3237,6 +3239,16 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 	inode_lock(inode);
 	filemap_invalidate_lock(inode->i_mapping);
 
+	i_size = i_size_read(inode);
+	remote_size = ictx->remote_i_size;
+	if (offset + len >= remote_size && offset < i_size) {
+		unsigned long long top = umin(offset + len, i_size);
+
+		rc = filemap_write_and_wait_range(inode->i_mapping, offset, top - 1);
+		if (rc < 0)
+			goto zero_range_exit;
+	}
+
 	/*
 	 * We zero the range through ioctl, so we need remove the page caches
 	 * first, otherwise the data may be inconsistent with the server.




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux