added to cifs-2.6.git for-next pending testing On Fri, May 24, 2024 at 9:23 AM David Howells <dhowells@xxxxxxxxxx> wrote: > > Occasionally, the generic/001 xfstest will fail indicating corruption in > one of the copy chains when run on cifs against a server that supports > FSCTL_DUPLICATE_EXTENTS_TO_FILE (eg. Samba with a share on btrfs). The > problem is that the remote_i_size value isn't updated by cifs_setsize() > when called by smb2_duplicate_extents(), but i_size *is*. > > This may cause cifs_remap_file_range() to then skip the bit after calling > ->duplicate_extents() that sets sizes. > > Fix this by calling netfs_resize_file() in smb2_duplicate_extents() before > calling cifs_setsize() to set i_size. > > This means we don't then need to call netfs_resize_file() upon return from > ->duplicate_extents(), but we also fix the test to compare against the pre-dup > inode size. > > [Note that this goes back before the addition of remote_i_size with the > netfs_inode struct. It should probably have been setting cifsi->server_eof > previously.] > > Fixes: cfc63fc8126a ("smb3: fix cached file size problems in duplicate extents (reflink)") > Signed-off-by: David Howells <dhowells@xxxxxxxxxx> > cc: Steve French <sfrench@xxxxxxxxx> > cc: Paulo Alcantara <pc@xxxxxxxxxxxxx> > cc: Shyam Prasad N <nspmangalore@xxxxxxxxx> > cc: Rohith Surabattula <rohiths.msft@xxxxxxxxx> > cc: Jeff Layton <jlayton@xxxxxxxxxx> > cc: linux-cifs@xxxxxxxxxxxxxxx > cc: netfs@xxxxxxxxxxxxxxx > --- > fs/smb/client/cifsfs.c | 6 +++--- > fs/smb/client/smb2ops.c | 1 + > 2 files changed, 4 insertions(+), 3 deletions(-) > > diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c > index 14810ffd15c8..bb86fc0641d8 100644 > --- a/fs/smb/client/cifsfs.c > +++ b/fs/smb/client/cifsfs.c > @@ -1227,7 +1227,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, > struct cifsFileInfo *smb_file_src = src_file->private_data; > struct cifsFileInfo *smb_file_target = dst_file->private_data; > struct cifs_tcon *target_tcon, *src_tcon; > - unsigned long long destend, fstart, fend, new_size; > + unsigned long long destend, fstart, fend, old_size, new_size; > unsigned int xid; > int rc; > > @@ -1294,6 +1294,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, > goto unlock; > if (fend > target_cifsi->netfs.zero_point) > target_cifsi->netfs.zero_point = fend + 1; > + old_size = target_cifsi->netfs.remote_i_size; > > /* Discard all the folios that overlap the destination region. */ > cifs_dbg(FYI, "about to discard pages %llx-%llx\n", fstart, fend); > @@ -1306,9 +1307,8 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, > if (target_tcon->ses->server->ops->duplicate_extents) { > rc = target_tcon->ses->server->ops->duplicate_extents(xid, > smb_file_src, smb_file_target, off, len, destoff); > - if (rc == 0 && new_size > i_size_read(target_inode)) { > + if (rc == 0 && new_size > old_size) { > truncate_setsize(target_inode, new_size); > - netfs_resize_file(&target_cifsi->netfs, new_size, true); > fscache_resize_cookie(cifs_inode_cookie(target_inode), > new_size); > } > diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c > index b87b70edd0be..4ce6c3121a7e 100644 > --- a/fs/smb/client/smb2ops.c > +++ b/fs/smb/client/smb2ops.c > @@ -2028,6 +2028,7 @@ smb2_duplicate_extents(const unsigned int xid, > * size will be queried on next revalidate, but it is important > * to make sure that file's cached size is updated immediately > */ > + netfs_resize_file(netfs_inode(inode), dest_off + len, true); > cifs_setsize(inode, dest_off + len); > } > rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, > > -- Thanks, Steve