smb: client: discard post-EOF pagecache when extending a file via copy range

cifs_file_copychunk_range() invalidated the pagecache only for the
destination region, so when a copy extends the file the folio straddling
the old EOF - which may hold data dirtied past EOF through an mmap - was
never dropped and became visible as file content once the file was
extended.

Start the invalidation at the smaller of the destination offset and the
old EOF.  filemap_invalidate_inode() writes back before invalidating
while i_size is still old, so nothing past the old EOF is flushed to the
server.

Fixes: 8101d6e112 ("cifs: Fix copy offload to flush destination region")
Reviewed-by: David Howells <dhowells@redhat.com>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Cc: Shyam Prasad N <sprasad@microsoft.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Bharath SM <bharathsm@microsoft.com>
Cc: stable@vger.kernel.org
This commit is contained in:
Paulo Alcantara 2026-09-20 16:37:41 -03:00
parent da4fe97fb6
commit 7b473ac7cd

View File

@ -1581,8 +1581,13 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
/* Flush and invalidate all the folios in the destination region. If
* the copy was successful, then some of the flush is extra overhead,
* but we need to allow for the copy failing in some way (eg. ENOSPC).
*
* Start at the old EOF when extending so the folio straddling it, which
* may hold data written past EOF through an mmap, is dropped too.
*/
rc = filemap_invalidate_inode(target_inode, true, destoff, destoff + len - 1);
rc = filemap_invalidate_inode(target_inode, true,
min(destoff, i_size_read(target_inode)),
destoff + len - 1);
if (rc)
goto unlock;