]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
cifs: Fix copy offload to flush destination region
authorDavid Howells <dhowells@redhat.com>
Tue, 27 Aug 2024 14:47:27 +0000 (15:47 +0100)
committerSteve French <stfrench@microsoft.com>
Wed, 28 Aug 2024 12:48:33 +0000 (07:48 -0500)
Fix cifs_file_copychunk_range() to flush the destination region before
invalidating it to avoid potential loss of data should the copy fail, in
whole or in part, in some way.

Fixes: 7b2404a886f8 ("cifs: Fix flushing, invalidation and file size with copy_file_range()")
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <stfrench@microsoft.com>
cc: Paulo Alcantara <pc@manguebit.com>
cc: Shyam Prasad N <nspmangalore@gmail.com>
cc: Rohith Surabattula <rohiths.msft@gmail.com>
cc: Matthew Wilcox <willy@infradead.org>
cc: Jeff Layton <jlayton@kernel.org>
cc: linux-cifs@vger.kernel.org
cc: linux-mm@kvack.org
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifsfs.c

index d89485235425aee542cfd503135f8a50f337ec88..2a2523c93944de68e82528f485de5ae19d7d23d8 100644 (file)
@@ -1341,7 +1341,6 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
        struct cifsFileInfo *smb_file_target;
        struct cifs_tcon *src_tcon;
        struct cifs_tcon *target_tcon;
-       unsigned long long destend, fstart, fend;
        ssize_t rc;
 
        cifs_dbg(FYI, "copychunk range\n");
@@ -1391,25 +1390,13 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
                        goto unlock;
        }
 
-       destend = destoff + len - 1;
-
-       /* Flush the folios at either end of the destination range to prevent
-        * accidental loss of dirty data outside of the range.
+       /* Flush and invalidate all the folios in the destination region.  If
+        * the copy was successful, then some of the flush is extra overhead,
+        * but we need to allow for the copy failing in some way (eg. ENOSPC).
         */
-       fstart = destoff;
-       fend = destend;
-
-       rc = cifs_flush_folio(target_inode, destoff, &fstart, &fend, true);
+       rc = filemap_invalidate_inode(target_inode, true, destoff, destoff + len - 1);
        if (rc)
                goto unlock;
-       rc = cifs_flush_folio(target_inode, destend, &fstart, &fend, false);
-       if (rc)
-               goto unlock;
-       if (fend > target_cifsi->netfs.zero_point)
-               target_cifsi->netfs.zero_point = fend + 1;
-
-       /* Discard all the folios that overlap the destination region. */
-       truncate_inode_pages_range(&target_inode->i_data, fstart, fend);
 
        fscache_invalidate(cifs_inode_cookie(target_inode), NULL,
                           i_size_read(target_inode), 0);