Tentatively merged into cifs-2.6.git for-next pending review and testing On Tue, Feb 22, 2022 at 7:14 PM Ronnie Sahlberg <lsahlber@xxxxxxxxxx> wrote: > > 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 <xifeng@xxxxxxxxxx> > Reported-by: kernel test robot <lkp@xxxxxxxxx> > Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> > --- > fs/cifs/smb2ops.c | 18 ++++++++++++++---- > 1 file changed, 14 insertions(+), 4 deletions(-) > > diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c > index af5d0830bc8a..891b11576e55 100644 > --- a/fs/cifs/smb2ops.c > +++ b/fs/cifs/smb2ops.c > @@ -25,6 +25,7 @@ > #include "smb2glob.h" > #include "cifs_ioctl.h" > #include "smbdirect.h" > +#include "fscache.h" > #include "fs_context.h" > > /* 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, > { > int rc; > unsigned int xid; > + struct inode *inode; > struct cifsFileInfo *cfile = file->private_data; > + struct cifsInodeInfo *cifsi; > __le64 eof; > > xid = get_xid(); > > - if (off >= i_size_read(file->f_inode) || > - off + len >= i_size_read(file->f_inode)) { > + inode = d_inode(cfile->dentry); > + cifsi = CIFS_I(inode); > + > + if (off >= i_size_read(inode) || > + off + len >= i_size_read(inode)) { > rc = -EINVAL; > goto out; > } > > rc = smb2_copychunk_range(xid, cfile, cfile, off + len, > - i_size_read(file->f_inode) - off - len, off); > + i_size_read(inode) - off - len, off); > if (rc < 0) > goto out; > > - eof = cpu_to_le64(i_size_read(file->f_inode) - len); > + eof = cpu_to_le64(i_size_read(inode) - len); > rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, > cfile->fid.volatile_fid, cfile->pid, &eof); > if (rc < 0) > goto out; > > rc = 0; > + > + cifsi->server_eof = i_size_read(inode) - len; > + truncate_setsize(inode, cifsi->server_eof); > + fscache_resize_cookie(cifs_inode_cookie(inode), cifsi->server_eof); > out: > free_xid(xid); > return rc; > -- > 2.30.2 > -- Thanks, Steve