Skip to content

Commit 84330d4

Browse files
Ronnie Sahlbergsmfrench
authored andcommitted
cifs: truncate the inode and mapping when we simulate fcollapse
RHBZ:1997367 When we collapse a range in smb3_collapse_range() we must make sure we update the inode size and pagecache accordingly. If not, both inode size and pagecahce may be stale until it is refreshed. This can be demonstrated for the inode size by running : xfs_io -i -f -c "truncate 320k" -c "fcollapse 64k 128k" -c "fiemap -v" \ /mnt/testfile where we can see the result of stale data in the fiemap output. The third line of the output is wrong, all this data should be truncated. EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..127]: hole 128 1: [128..383]: 128..383 256 0x1 2: [384..639]: hole 256 And the correct output, when the inode size has been updated correctly should look like this: EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..127]: hole 128 1: [128..383]: 128..383 256 0x1 Reported-by: Xiaoli Feng <[email protected]> Reported-by: kernel test robot <[email protected]> Cc: [email protected] Signed-off-by: Ronnie Sahlberg <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 47178c7 commit 84330d4

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

fs/cifs/smb2ops.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "smb2glob.h"
2626
#include "cifs_ioctl.h"
2727
#include "smbdirect.h"
28+
#include "fscache.h"
2829
#include "fs_context.h"
2930

3031
/* Change credits for different ops and return the total number of credits */
@@ -3887,29 +3888,38 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
38873888
{
38883889
int rc;
38893890
unsigned int xid;
3891+
struct inode *inode;
38903892
struct cifsFileInfo *cfile = file->private_data;
3893+
struct cifsInodeInfo *cifsi;
38913894
__le64 eof;
38923895

38933896
xid = get_xid();
38943897

3895-
if (off >= i_size_read(file->f_inode) ||
3896-
off + len >= i_size_read(file->f_inode)) {
3898+
inode = d_inode(cfile->dentry);
3899+
cifsi = CIFS_I(inode);
3900+
3901+
if (off >= i_size_read(inode) ||
3902+
off + len >= i_size_read(inode)) {
38973903
rc = -EINVAL;
38983904
goto out;
38993905
}
39003906

39013907
rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
3902-
i_size_read(file->f_inode) - off - len, off);
3908+
i_size_read(inode) - off - len, off);
39033909
if (rc < 0)
39043910
goto out;
39053911

3906-
eof = cpu_to_le64(i_size_read(file->f_inode) - len);
3912+
eof = cpu_to_le64(i_size_read(inode) - len);
39073913
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
39083914
cfile->fid.volatile_fid, cfile->pid, &eof);
39093915
if (rc < 0)
39103916
goto out;
39113917

39123918
rc = 0;
3919+
3920+
cifsi->server_eof = i_size_read(inode) - len;
3921+
truncate_setsize(inode, cifsi->server_eof);
3922+
fscache_resize_cookie(cifs_inode_cookie(inode), cifsi->server_eof);
39133923
out:
39143924
free_xid(xid);
39153925
return rc;

0 commit comments

Comments
 (0)