From 8d4d197f0a3880e4dde3580ee9cd84bc20d587ee Mon Sep 17 00:00:00 2001 From: Cheyenne Wills Date: Mon, 9 Sep 2024 10:04:20 -0600 Subject: [PATCH] Linux: Test for missing generic_file_splice_read In commit: 'Linux 6.5: Replace generic_file_splice_read' (0e06eb78f2) we check the version of Linux to determine to use the newer filemap_splice_read() or the older generic_file_splice_read(). openSUSE 15.6 uses a Linux 6.4 kernel, but is also including the Linux 6.5 commit: 'splice: Remove generic_file_splice_read()' (c6585011bc) When this commit included in Linux 6.4, the kernel module fails to build. In order to handle the case where Linux distributions are including the (c6585011bc) commit in earlier kernels, we need to see if generic_file_splice_read() is present; if not, we should use the newer filemap_splice_read(). With the (0e06eb78f2) commit there was a preference for using generic_file_splice_read() over filemap_splice_read() until Linux 6.5 (which contained additional updates surrounding filemap_splice_read()). See the (0e06eb78f2) commit for additional details. With this commit, we are still preferring generic_file_splice_read() when it is available on kernels less than Linux 6.5. Change-Id: Idfc75e474d4e21a9375ee115dad0929bad482e27 Reviewed-on: https://gerrit.openafs.org/15846 Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Andrew Deason Reviewed-by: Michael Meffie --- src/afs/LINUX/osi_vnodeops.c | 2 +- src/cf/linux-kernel-func.m4 | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 1da52c4879..3ef4274fbb 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1013,7 +1013,7 @@ struct file_operations afs_file_fops = { # else .splice_write = generic_file_splice_write, # endif -# if LINUX_VERSION_CODE >= KERNEL_VERSION(6,5,0) +# if defined(HAVE_LINUX_NO_GENERIC_FILE_SPLICE_READ) .splice_read = filemap_splice_read, # else .splice_read = generic_file_splice_read, diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4 index b53005273a..6bb9cd477b 100644 --- a/src/cf/linux-kernel-func.m4 +++ b/src/cf/linux-kernel-func.m4 @@ -264,6 +264,33 @@ AC_CHECK_LINUX_FUNC([filemap_alloc_folio], [[static struct folio *folio; folio = filemap_alloc_folio(0, 0);]]) +dnl Linux 6.3 introduced filemap_splice_read(), which is a replacement for +dnl generic_file_splice_read(). But filemap_splice_read() at this point was not +dnl fully supported for use with all filesystems. +dnl +dnl Linux 6.5 removed generic_file_splice_read(), and changed +dnl filemap_splice_read() to be supported for all filesystems. +dnl +dnl To decide which function to use, we cannot simply check for +dnl filemap_splice_read(), since we need to avoid using filemap_splice_read() +dnl until it was fixed in Linux 6.5. We cannot simply check the Linux version +dnl number, since some downstream kernels fix filemap_splice_read() and remove +dnl generic_file_splice_read() before Linux 6.5 (e.g., openSUSE 15.6). +dnl +dnl To decide what function to use, we check if generic_file_splice_read() is +dnl missing. If generic_file_splice_read() is missing, use +dnl filemap_splice_read(); otherwise, use generic_file_splice_read(). +dnl +dnl To check if generic_file_splice_read() is missing, define our own +dnl generic_file_splice_read() function with a conflicting signature. If we can +dnl define it, the real generic_file_splice_read() must be missing. +AC_CHECK_LINUX_FUNC([no_generic_file_splice_read], + [[#include + char *generic_file_splice_read(char *p); + char *generic_file_splice_read(char *p) { return p + 1; }]], + [[static char buff[10], *ap; + ap = generic_file_splice_read(buff); ]]) + dnl Consequences - things which get set as a result of the dnl above tests AS_IF([test "x$ac_cv_linux_func_d_alloc_anon" = "xno"],