From: Namjae Jeon Date: Thu, 25 Sep 2025 12:15:20 +0000 (+0900) Subject: ksmbd: copy overlapped range within the same file X-Git-Tag: v6.18-rc1~111^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c20988c21751ef67df4191e262675e231610e9ab;p=thirdparty%2Fkernel%2Flinux.git ksmbd: copy overlapped range within the same file cifs.ko request to copy overlapped range within the same file. ksmbd is using vfs_copy_file_range for this, vfs_copy_file_range() does not allow overlapped copying within the same file. This patch use do_splice_direct() if offset and length are overlapped. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index 1cfa688904b2c..c96e5d934ba98 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "glob.h" #include "oplock.h" @@ -1829,8 +1830,19 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work, if (src_off + len > src_file_size) return -E2BIG; - ret = vfs_copy_file_range(src_fp->filp, src_off, - dst_fp->filp, dst_off, len, 0); + /* + * vfs_copy_file_range does not allow overlapped copying + * within the same file. + */ + if (file_inode(src_fp->filp) == file_inode(dst_fp->filp) && + dst_off + len > src_off && + dst_off < src_off + len) + ret = do_splice_direct(src_fp->filp, &src_off, + dst_fp->filp, &dst_off, + min_t(size_t, len, MAX_RW_COUNT), 0); + else + ret = vfs_copy_file_range(src_fp->filp, src_off, + dst_fp->filp, dst_off, len, 0); if (ret == -EOPNOTSUPP || ret == -EXDEV) ret = vfs_copy_file_range(src_fp->filp, src_off, dst_fp->filp, dst_off, len,