Skip to content

Commit 1551f8f

Browse files
committed
Merge tag '6.0-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Five fixes, all also marked for stable: - fixes for collapse range and insert range (also fixes xfstest generic/031) - memory leak fix" * tag '6.0-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: fix small mempool leak in SMB2_negotiate() smb3: use filemap_write_and_wait_range instead of filemap_write_and_wait smb3: fix temporary data corruption in insert range smb3: fix temporary data corruption in collapse range smb3: Move the flush out of smb2_copychunk_range() into its callers
2 parents 0c95f02 + 27893df commit 1551f8f

File tree

3 files changed

+55
-32
lines changed

3 files changed

+55
-32
lines changed

fs/cifs/cifsfs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,12 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
12481248
lock_two_nondirectories(target_inode, src_inode);
12491249

12501250
cifs_dbg(FYI, "about to flush pages\n");
1251+
1252+
rc = filemap_write_and_wait_range(src_inode->i_mapping, off,
1253+
off + len - 1);
1254+
if (rc)
1255+
goto out;
1256+
12511257
/* should we flush first and last page first */
12521258
truncate_inode_pages(&target_inode->i_data, 0);
12531259

fs/cifs/smb2ops.c

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,17 +1600,8 @@ smb2_copychunk_range(const unsigned int xid,
16001600
int chunks_copied = 0;
16011601
bool chunk_sizes_updated = false;
16021602
ssize_t bytes_written, total_bytes_written = 0;
1603-
struct inode *inode;
16041603

16051604
pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
1606-
1607-
/*
1608-
* We need to flush all unwritten data before we can send the
1609-
* copychunk ioctl to the server.
1610-
*/
1611-
inode = d_inode(trgtfile->dentry);
1612-
filemap_write_and_wait(inode->i_mapping);
1613-
16141605
if (pcchunk == NULL)
16151606
return -ENOMEM;
16161607

@@ -3678,39 +3669,50 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
36783669
{
36793670
int rc;
36803671
unsigned int xid;
3681-
struct inode *inode;
3672+
struct inode *inode = file_inode(file);
36823673
struct cifsFileInfo *cfile = file->private_data;
3683-
struct cifsInodeInfo *cifsi;
3674+
struct cifsInodeInfo *cifsi = CIFS_I(inode);
36843675
__le64 eof;
3676+
loff_t old_eof;
36853677

36863678
xid = get_xid();
36873679

3688-
inode = d_inode(cfile->dentry);
3689-
cifsi = CIFS_I(inode);
3680+
inode_lock(inode);
36903681

3691-
if (off >= i_size_read(inode) ||
3692-
off + len >= i_size_read(inode)) {
3682+
old_eof = i_size_read(inode);
3683+
if ((off >= old_eof) ||
3684+
off + len >= old_eof) {
36933685
rc = -EINVAL;
36943686
goto out;
36953687
}
36963688

3689+
filemap_invalidate_lock(inode->i_mapping);
3690+
rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof - 1);
3691+
if (rc < 0)
3692+
goto out_2;
3693+
3694+
truncate_pagecache_range(inode, off, old_eof);
3695+
36973696
rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
3698-
i_size_read(inode) - off - len, off);
3697+
old_eof - off - len, off);
36993698
if (rc < 0)
3700-
goto out;
3699+
goto out_2;
37013700

3702-
eof = cpu_to_le64(i_size_read(inode) - len);
3701+
eof = cpu_to_le64(old_eof - len);
37033702
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
37043703
cfile->fid.volatile_fid, cfile->pid, &eof);
37053704
if (rc < 0)
3706-
goto out;
3705+
goto out_2;
37073706

37083707
rc = 0;
37093708

37103709
cifsi->server_eof = i_size_read(inode) - len;
37113710
truncate_setsize(inode, cifsi->server_eof);
37123711
fscache_resize_cookie(cifs_inode_cookie(inode), cifsi->server_eof);
3712+
out_2:
3713+
filemap_invalidate_unlock(inode->i_mapping);
37133714
out:
3715+
inode_unlock(inode);
37143716
free_xid(xid);
37153717
return rc;
37163718
}
@@ -3721,34 +3723,47 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
37213723
int rc;
37223724
unsigned int xid;
37233725
struct cifsFileInfo *cfile = file->private_data;
3726+
struct inode *inode = file_inode(file);
37243727
__le64 eof;
3725-
__u64 count;
3728+
__u64 count, old_eof;
37263729

37273730
xid = get_xid();
37283731

3729-
if (off >= i_size_read(file->f_inode)) {
3732+
inode_lock(inode);
3733+
3734+
old_eof = i_size_read(inode);
3735+
if (off >= old_eof) {
37303736
rc = -EINVAL;
37313737
goto out;
37323738
}
37333739

3734-
count = i_size_read(file->f_inode) - off;
3735-
eof = cpu_to_le64(i_size_read(file->f_inode) + len);
3740+
count = old_eof - off;
3741+
eof = cpu_to_le64(old_eof + len);
3742+
3743+
filemap_invalidate_lock(inode->i_mapping);
3744+
rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof + len - 1);
3745+
if (rc < 0)
3746+
goto out_2;
3747+
truncate_pagecache_range(inode, off, old_eof);
37363748

37373749
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
37383750
cfile->fid.volatile_fid, cfile->pid, &eof);
37393751
if (rc < 0)
3740-
goto out;
3752+
goto out_2;
37413753

37423754
rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
37433755
if (rc < 0)
3744-
goto out;
3756+
goto out_2;
37453757

3746-
rc = smb3_zero_range(file, tcon, off, len, 1);
3758+
rc = smb3_zero_data(file, tcon, off, len, xid);
37473759
if (rc < 0)
3748-
goto out;
3760+
goto out_2;
37493761

37503762
rc = 0;
3763+
out_2:
3764+
filemap_invalidate_unlock(inode->i_mapping);
37513765
out:
3766+
inode_unlock(inode);
37523767
free_xid(xid);
37533768
return rc;
37543769
}

fs/cifs/smb2pdu.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -965,16 +965,17 @@ SMB2_negotiate(const unsigned int xid,
965965
} else if (rc != 0)
966966
goto neg_exit;
967967

968+
rc = -EIO;
968969
if (strcmp(server->vals->version_string,
969970
SMB3ANY_VERSION_STRING) == 0) {
970971
if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
971972
cifs_server_dbg(VFS,
972973
"SMB2 dialect returned but not requested\n");
973-
return -EIO;
974+
goto neg_exit;
974975
} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
975976
cifs_server_dbg(VFS,
976977
"SMB2.1 dialect returned but not requested\n");
977-
return -EIO;
978+
goto neg_exit;
978979
} else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
979980
/* ops set to 3.0 by default for default so update */
980981
server->ops = &smb311_operations;
@@ -985,7 +986,7 @@ SMB2_negotiate(const unsigned int xid,
985986
if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
986987
cifs_server_dbg(VFS,
987988
"SMB2 dialect returned but not requested\n");
988-
return -EIO;
989+
goto neg_exit;
989990
} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
990991
/* ops set to 3.0 by default for default so update */
991992
server->ops = &smb21_operations;
@@ -999,7 +1000,7 @@ SMB2_negotiate(const unsigned int xid,
9991000
/* if requested single dialect ensure returned dialect matched */
10001001
cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n",
10011002
le16_to_cpu(rsp->DialectRevision));
1002-
return -EIO;
1003+
goto neg_exit;
10031004
}
10041005

10051006
cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
@@ -1017,9 +1018,10 @@ SMB2_negotiate(const unsigned int xid,
10171018
else {
10181019
cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n",
10191020
le16_to_cpu(rsp->DialectRevision));
1020-
rc = -EIO;
10211021
goto neg_exit;
10221022
}
1023+
1024+
rc = 0;
10231025
server->dialect = le16_to_cpu(rsp->DialectRevision);
10241026

10251027
/*

0 commit comments

Comments
 (0)