]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Linux 6.8 compat: use splice_copy_file_range() for fallback
authorRob N <robn@despairlabs.com>
Wed, 20 Mar 2024 23:46:15 +0000 (10:46 +1100)
committerGitHub <noreply@github.com>
Wed, 20 Mar 2024 23:46:15 +0000 (16:46 -0700)
Linux 6.8 removes generic_copy_file_range(), which had been reduced to a
simple wrapper around splice_copy_file_range(). Detect that function
directly and use it if generic_ is not available.

Sponsored-by: https://despairlabs.com/sponsor/
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <robn@despairlabs.com>
Closes #15930
Closes #15931

config/kernel-vfs-file_range.m4
config/kernel.m4
module/os/linux/zfs/zpl_file_range.c

index cc96404d8bbe65b6f3087c0d8b2dea3e7c9c74e2..8a5cbe2eeeedc524cafbeb4996024dc2b66bba71 100644 (file)
@@ -16,6 +16,9 @@ dnl #
 dnl # 5.3: VFS copy_file_range() expected to do its own fallback,
 dnl #      generic_copy_file_range() added to support it
 dnl #
+dnl # 6.8: generic_copy_file_range() removed, replaced by
+dnl #      splice_copy_file_range()
+dnl #
 AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_COPY_FILE_RANGE], [
        ZFS_LINUX_TEST_SRC([vfs_copy_file_range], [
                #include <linux/fs.h>
@@ -72,6 +75,30 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_GENERIC_COPY_FILE_RANGE], [
        ])
 ])
 
+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_SPLICE_COPY_FILE_RANGE], [
+       ZFS_LINUX_TEST_SRC([splice_copy_file_range], [
+               #include <linux/splice.h>
+       ], [
+               struct file *src_file __attribute__ ((unused)) = NULL;
+               loff_t src_off __attribute__ ((unused)) = 0;
+               struct file *dst_file __attribute__ ((unused)) = NULL;
+               loff_t dst_off __attribute__ ((unused)) = 0;
+               size_t len __attribute__ ((unused)) = 0;
+               splice_copy_file_range(src_file, src_off, dst_file, dst_off,
+                   len);
+       ])
+])
+AC_DEFUN([ZFS_AC_KERNEL_VFS_SPLICE_COPY_FILE_RANGE], [
+       AC_MSG_CHECKING([whether splice_copy_file_range() is available])
+       ZFS_LINUX_TEST_RESULT([splice_copy_file_range], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_VFS_SPLICE_COPY_FILE_RANGE, 1,
+                   [splice_copy_file_range() is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
 AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_CLONE_FILE_RANGE], [
        ZFS_LINUX_TEST_SRC([vfs_clone_file_range], [
                #include <linux/fs.h>
index e3f8645774c5323da564697562f2011ab81180fd..1d0c5a27fc7f3a62d95b19351194c6cb01e090a1 100644 (file)
@@ -118,6 +118,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
        ZFS_AC_KERNEL_SRC_VFS_IOV_ITER
        ZFS_AC_KERNEL_SRC_VFS_COPY_FILE_RANGE
        ZFS_AC_KERNEL_SRC_VFS_GENERIC_COPY_FILE_RANGE
+       ZFS_AC_KERNEL_SRC_VFS_SPLICE_COPY_FILE_RANGE
        ZFS_AC_KERNEL_SRC_VFS_REMAP_FILE_RANGE
        ZFS_AC_KERNEL_SRC_VFS_CLONE_FILE_RANGE
        ZFS_AC_KERNEL_SRC_VFS_DEDUPE_FILE_RANGE
@@ -266,6 +267,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
        ZFS_AC_KERNEL_VFS_IOV_ITER
        ZFS_AC_KERNEL_VFS_COPY_FILE_RANGE
        ZFS_AC_KERNEL_VFS_GENERIC_COPY_FILE_RANGE
+       ZFS_AC_KERNEL_VFS_SPLICE_COPY_FILE_RANGE
        ZFS_AC_KERNEL_VFS_REMAP_FILE_RANGE
        ZFS_AC_KERNEL_VFS_CLONE_FILE_RANGE
        ZFS_AC_KERNEL_VFS_DEDUPE_FILE_RANGE
index 3065d54fa9da5f290e289da45d0df15b4a62b42e..64728fdb118750c955a627562dabb82190bd9ae8 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/compat.h>
 #endif
 #include <linux/fs.h>
+#ifdef HAVE_VFS_SPLICE_COPY_FILE_RANGE
+#include <linux/splice.h>
+#endif
 #include <sys/file.h>
 #include <sys/zfs_znode.h>
 #include <sys/zfs_vnops.h>
@@ -102,7 +105,7 @@ zpl_copy_file_range(struct file *src_file, loff_t src_off,
        ret = zpl_clone_file_range_impl(src_file, src_off,
            dst_file, dst_off, len);
 
-#ifdef HAVE_VFS_GENERIC_COPY_FILE_RANGE
+#if defined(HAVE_VFS_GENERIC_COPY_FILE_RANGE)
        /*
         * Since Linux 5.3 the filesystem driver is responsible for executing
         * an appropriate fallback, and a generic fallback function is provided.
@@ -111,6 +114,15 @@ zpl_copy_file_range(struct file *src_file, loff_t src_off,
            ret == -EAGAIN)
                ret = generic_copy_file_range(src_file, src_off, dst_file,
                    dst_off, len, flags);
+#elif defined(HAVE_VFS_SPLICE_COPY_FILE_RANGE)
+       /*
+        * Since 6.8 the fallback function is called splice_copy_file_range
+        * and has a slightly different signature.
+        */
+       if (ret == -EOPNOTSUPP || ret == -EINVAL || ret == -EXDEV ||
+           ret == -EAGAIN)
+               ret = splice_copy_file_range(src_file, src_off, dst_file,
+                   dst_off, len);
 #else
        /*
         * Before Linux 5.3 the filesystem has to return -EOPNOTSUPP to signal
@@ -118,7 +130,7 @@ zpl_copy_file_range(struct file *src_file, loff_t src_off,
         */
        if (ret == -EINVAL || ret == -EXDEV || ret == -EAGAIN)
                ret = -EOPNOTSUPP;
-#endif /* HAVE_VFS_GENERIC_COPY_FILE_RANGE */
+#endif /* HAVE_VFS_GENERIC_COPY_FILE_RANGE || HAVE_VFS_SPLICE_COPY_FILE_RANGE */
 
        return (ret);
 }