]> git.ipfire.org Git - people/ms/linux.git/blobdiff - fs/cifs/smb2ops.c
Merge tag 'soc-fixes-6.0-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[people/ms/linux.git] / fs / cifs / smb2ops.c
index 4810bd62266a573ff02414dfec45510dc4a0af39..421be43af42533d2e254157b74ec0c166c6ff310 100644 (file)
@@ -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;
        }
 
+       filemap_invalidate_lock(inode->i_mapping);
+       rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof - 1);
+       if (rc < 0)
+               goto out_2;
+
+       truncate_pagecache_range(inode, off, old_eof);
+
        rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
-                                 i_size_read(inode) - off - len, off);
+                                 old_eof - off - len, off);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
-       eof = cpu_to_le64(i_size_read(inode) - len);
+       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;
 }