]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
smb3 client: fix return code mapping of remap_file_range
authorSteve French <stfrench@microsoft.com>
Sun, 24 Aug 2025 02:15:59 +0000 (21:15 -0500)
committerSteve French <stfrench@microsoft.com>
Mon, 25 Aug 2025 14:40:38 +0000 (09:40 -0500)
We were returning -EOPNOTSUPP for various remap_file_range cases
but for some of these the copy_file_range_syscall() requires -EINVAL
to be returned (e.g. where source and target file ranges overlap when
source and target are the same file). This fixes xfstest generic/157
which was expecting EINVAL for that (and also e.g. for when the src
offset is beyond end of file).

Cc: stable@vger.kernel.org
Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifsfs.c

index 3bd85ab2deb1924412fb726778a48804f0cc5812..e1848276bab41364f894f5f92d7ec08f343aeb1c 100644 (file)
@@ -1358,6 +1358,20 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
                        truncate_setsize(target_inode, new_size);
                        fscache_resize_cookie(cifs_inode_cookie(target_inode),
                                              new_size);
+               } else if (rc == -EOPNOTSUPP) {
+                       /*
+                        * copy_file_range syscall man page indicates EINVAL
+                        * is returned e.g when "fd_in and fd_out refer to the
+                        * same file and the source and target ranges overlap."
+                        * Test generic/157 was what showed these cases where
+                        * we need to remap EOPNOTSUPP to EINVAL
+                        */
+                       if (off >= src_inode->i_size) {
+                               rc = -EINVAL;
+                       } else if (src_inode == target_inode) {
+                               if (off + len > destoff)
+                                       rc = -EINVAL;
+                       }
                }
                if (rc == 0 && new_size > target_cifsi->netfs.zero_point)
                        target_cifsi->netfs.zero_point = new_size;