Skip to content

Commit

Permalink
cifs: destage any unwritten data to the server before calling copychu…
Browse files Browse the repository at this point in the history
…nk_write

[ Upstream commit f5d0f92 ]

because the copychunk_write might cover a region of the file that has not yet
been sent to the server and thus fail.

A simple way to reproduce this is:
truncate -s 0 /mnt/testfile; strace -f -o x -ttT xfs_io -i -f -c 'pwrite 0k 128k' -c 'fcollapse 16k 24k' /mnt/testfile

the issue is that the 'pwrite 0k 128k' becomes rearranged on the wire with
the 'fcollapse 16k 24k' due to write-back caching.

fcollapse is implemented in cifs.ko as a SMB2 IOCTL(COPYCHUNK_WRITE) call
and it will fail serverside since the file is still 0b in size serverside
until the writes have been destaged.
To avoid this we must ensure that we destage any unwritten data to the
server before calling COPYCHUNK_WRITE.

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1997373
Reported-by: Xiaoli Feng <xifeng@redhat.com>
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Ronnie Sahlberg authored and gregkh committed May 9, 2022
1 parent 4640802 commit 3bb73c4
Showing 1 changed file with 8 additions and 0 deletions.
8 changes: 8 additions & 0 deletions fs/cifs/smb2ops.c
Expand Up @@ -1849,9 +1849,17 @@ smb2_copychunk_range(const unsigned int xid,
int chunks_copied = 0;
bool chunk_sizes_updated = false;
ssize_t bytes_written, total_bytes_written = 0;
struct inode *inode;

pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);

/*
* We need to flush all unwritten data before we can send the
* copychunk ioctl to the server.
*/
inode = d_inode(trgtfile->dentry);
filemap_write_and_wait(inode->i_mapping);

if (pcchunk == NULL)
return -ENOMEM;

Expand Down

0 comments on commit 3bb73c4

Please sign in to comment.