mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
5 cifs/smb3 fixes, all also for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmMRUSgACgkQiiy9cAdy T1GjCAv+LDYvl9tjzzCuA406CYiOuqoRghfHFjJ8WS90kVNhqN3de13DjydpWOAf YbeNCRMUJ5goVCUTHAuEIXLnDAu4Xdz/SRGkBnTYM7As7iBRvLlmbNfGPavZVUPB Up1xo2RIv3fcNJ2fe8Cfk+oGFhQ4NmJDcsguEOQhl4UTVxRSnm+zpMwEA/yJnjzL gC+bsw7iw6bxQOr14HOxGvPeztULs3eizGw4xNRSHnxfncStOrPH8YlUVvVLy44f 0ae07UxhEwojHIGvxR8h8y2h8F0cJ9nJRH0NK8wCsG9MfbXhEBLc4p/4+2CDNqZC ekpwDBIyG/h5/TbjmNsw8L5Iu292tBAYzpXX3KaMDinBqQm/WxYhtxnGJJDtRoHI dbflQC4ZELzlHDKf7gaOvRaQpBYJblnrfMM5j7NnWAXY2YjNzLZ79jTI390ET//C HAVLtdhaLKyAPpzU2/XCAEs1tEHTo4gHWnb5GpR8jCRHoUccZwz4Y9ZKW55Z2evv htMLLBiC =gRo4 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
1551f8f21e
@ -1248,6 +1248,12 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
|
||||
lock_two_nondirectories(target_inode, src_inode);
|
||||
|
||||
cifs_dbg(FYI, "about to flush pages\n");
|
||||
|
||||
rc = filemap_write_and_wait_range(src_inode->i_mapping, off,
|
||||
off + len - 1);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
/* should we flush first and last page first */
|
||||
truncate_inode_pages(&target_inode->i_data, 0);
|
||||
|
||||
|
@ -1600,17 +1600,8 @@ 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;
|
||||
|
||||
@ -3678,39 +3669,50 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
|
||||
{
|
||||
int rc;
|
||||
unsigned int xid;
|
||||
struct inode *inode;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct cifsFileInfo *cfile = file->private_data;
|
||||
struct cifsInodeInfo *cifsi;
|
||||
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
||||
__le64 eof;
|
||||
loff_t old_eof;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
inode = d_inode(cfile->dentry);
|
||||
cifsi = CIFS_I(inode);
|
||||
inode_lock(inode);
|
||||
|
||||
if (off >= i_size_read(inode) ||
|
||||
off + len >= i_size_read(inode)) {
|
||||
old_eof = i_size_read(inode);
|
||||
if ((off >= old_eof) ||
|
||||
off + len >= old_eof) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
|
||||
i_size_read(inode) - off - len, off);
|
||||
filemap_invalidate_lock(inode->i_mapping);
|
||||
rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof - 1);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
goto out_2;
|
||||
|
||||
eof = cpu_to_le64(i_size_read(inode) - len);
|
||||
truncate_pagecache_range(inode, off, old_eof);
|
||||
|
||||
rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
|
||||
old_eof - off - len, off);
|
||||
if (rc < 0)
|
||||
goto out_2;
|
||||
|
||||
eof = cpu_to_le64(old_eof - len);
|
||||
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, cfile->pid, &eof);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
goto out_2;
|
||||
|
||||
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_2:
|
||||
filemap_invalidate_unlock(inode->i_mapping);
|
||||
out:
|
||||
inode_unlock(inode);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
@ -3721,34 +3723,47 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
|
||||
int rc;
|
||||
unsigned int xid;
|
||||
struct cifsFileInfo *cfile = file->private_data;
|
||||
struct inode *inode = file_inode(file);
|
||||
__le64 eof;
|
||||
__u64 count;
|
||||
__u64 count, old_eof;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
if (off >= i_size_read(file->f_inode)) {
|
||||
inode_lock(inode);
|
||||
|
||||
old_eof = i_size_read(inode);
|
||||
if (off >= old_eof) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
count = i_size_read(file->f_inode) - off;
|
||||
eof = cpu_to_le64(i_size_read(file->f_inode) + len);
|
||||
count = old_eof - off;
|
||||
eof = cpu_to_le64(old_eof + len);
|
||||
|
||||
filemap_invalidate_lock(inode->i_mapping);
|
||||
rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof + len - 1);
|
||||
if (rc < 0)
|
||||
goto out_2;
|
||||
truncate_pagecache_range(inode, off, old_eof);
|
||||
|
||||
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, cfile->pid, &eof);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
goto out_2;
|
||||
|
||||
rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
goto out_2;
|
||||
|
||||
rc = smb3_zero_range(file, tcon, off, len, 1);
|
||||
rc = smb3_zero_data(file, tcon, off, len, xid);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
goto out_2;
|
||||
|
||||
rc = 0;
|
||||
out_2:
|
||||
filemap_invalidate_unlock(inode->i_mapping);
|
||||
out:
|
||||
inode_unlock(inode);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
@ -965,16 +965,17 @@ SMB2_negotiate(const unsigned int xid,
|
||||
} else if (rc != 0)
|
||||
goto neg_exit;
|
||||
|
||||
rc = -EIO;
|
||||
if (strcmp(server->vals->version_string,
|
||||
SMB3ANY_VERSION_STRING) == 0) {
|
||||
if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
|
||||
cifs_server_dbg(VFS,
|
||||
"SMB2 dialect returned but not requested\n");
|
||||
return -EIO;
|
||||
goto neg_exit;
|
||||
} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
|
||||
cifs_server_dbg(VFS,
|
||||
"SMB2.1 dialect returned but not requested\n");
|
||||
return -EIO;
|
||||
goto neg_exit;
|
||||
} else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
|
||||
/* ops set to 3.0 by default for default so update */
|
||||
server->ops = &smb311_operations;
|
||||
@ -985,7 +986,7 @@ SMB2_negotiate(const unsigned int xid,
|
||||
if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
|
||||
cifs_server_dbg(VFS,
|
||||
"SMB2 dialect returned but not requested\n");
|
||||
return -EIO;
|
||||
goto neg_exit;
|
||||
} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
|
||||
/* ops set to 3.0 by default for default so update */
|
||||
server->ops = &smb21_operations;
|
||||
@ -999,7 +1000,7 @@ SMB2_negotiate(const unsigned int xid,
|
||||
/* if requested single dialect ensure returned dialect matched */
|
||||
cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n",
|
||||
le16_to_cpu(rsp->DialectRevision));
|
||||
return -EIO;
|
||||
goto neg_exit;
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
|
||||
@ -1017,9 +1018,10 @@ SMB2_negotiate(const unsigned int xid,
|
||||
else {
|
||||
cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n",
|
||||
le16_to_cpu(rsp->DialectRevision));
|
||||
rc = -EIO;
|
||||
goto neg_exit;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
server->dialect = le16_to_cpu(rsp->DialectRevision);
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user