summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve French <stfrench@microsoft.com>2024-05-16 00:59:01 +0300
committerSteve French <stfrench@microsoft.com>2024-05-16 01:22:59 +0300
commita395726cf823fe8f62f1b8c3829010e5652ce98c (patch)
treeeea9d5f3fa217a1e6e5766880b4c9e0484f071f9
parent1ab1bd2f6a5fd876d1980d6ade74ce5f83807baf (diff)
downloadlinux-a395726cf823fe8f62f1b8c3829010e5652ce98c.tar.xz
cifs: fix data corruption in read after invalidate
When invalidating a file as part of breaking a lease, the folios holding the file data are disposed of, and truncate calls ->invalidate_folio() to get rid of them rather than calling ->release_folio(). This means that the netfs_inode::zero_point value didn't get updated in current upstream code to reflect the point after which we can assume that the server will only return zeroes, and future reads will then return blocks of zeroes if the file got extended for any region beyond the old zero point. Fix this by updating zero_point before invalidating the inode in cifs_revalidate_mapping(). Suggested-by: David Howells <dhowells@redhat.com> Fixes: 3ee1a1fc3981 ("cifs: Cut over to using netfslib") Reviewed-by: David Howells <dhowell@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/smb/client/inode.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index 5d4b0fd3a59e..262576573eb5 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -2465,7 +2465,8 @@ int
cifs_revalidate_mapping(struct inode *inode)
{
int rc;
- unsigned long *flags = &CIFS_I(inode)->flags;
+ struct cifsInodeInfo *cifs_inode = CIFS_I(inode);
+ unsigned long *flags = &cifs_inode->flags;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
/* swapfiles are not supposed to be shared */
@@ -2482,6 +2483,7 @@ cifs_revalidate_mapping(struct inode *inode)
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
goto skip_invalidate;
+ cifs_inode->netfs.zero_point = cifs_inode->netfs.remote_i_size;
rc = filemap_invalidate_inode(inode, true, 0, LLONG_MAX);
if (rc) {
cifs_dbg(VFS, "%s: invalidate inode %p failed with rc %d\n",