Commit 9c8b7a29 authored by David Howells's avatar David Howells Committed by Steve French

smb3: fix temporary data corruption in insert range

insert range doesn't discard the affected cached region
so can risk temporarily corrupting file data.

Also includes some minor cleanup (avoiding rereading
inode size repeatedly unnecessarily) to make it clearer.

Cc: stable@vger.kernel.org
Fixes: 7fe6fe95 ("cifs: add FALLOC_FL_INSERT_RANGE support")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent fa30a81f
...@@ -3722,35 +3722,43 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon, ...@@ -3722,35 +3722,43 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
struct cifsFileInfo *cfile = file->private_data; struct cifsFileInfo *cfile = file->private_data;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
__le64 eof; __le64 eof;
__u64 count; __u64 count, old_eof;
xid = get_xid(); xid = get_xid();
if (off >= i_size_read(inode)) { inode_lock(inode);
old_eof = i_size_read(inode);
if (off >= old_eof) {
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
count = i_size_read(inode) - off; count = old_eof - off;
eof = cpu_to_le64(i_size_read(inode) + len); eof = cpu_to_le64(old_eof + len);
filemap_invalidate_lock(inode->i_mapping);
filemap_write_and_wait(inode->i_mapping); filemap_write_and_wait(inode->i_mapping);
truncate_pagecache_range(inode, off, old_eof);
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, cfile->pid, &eof); cfile->fid.volatile_fid, cfile->pid, &eof);
if (rc < 0) if (rc < 0)
goto out; goto out_2;
rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len); rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
if (rc < 0) if (rc < 0)
goto out; goto out_2;
rc = smb3_zero_range(file, tcon, off, len, 1); rc = smb3_zero_data(file, tcon, off, len, xid);
if (rc < 0) if (rc < 0)
goto out; goto out_2;
rc = 0; rc = 0;
out_2:
filemap_invalidate_unlock(inode->i_mapping);
out: out:
inode_unlock(inode);
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment