aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Larsson <catacombae@gmail.com>2026-02-02 22:16:10 +0000
committerGitHub <noreply@github.com>2026-02-02 22:16:10 +0000
commit7e33476a7c838eefafe4a8a6ecd1da5220cfacfa (patch)
tree50310fae787f988e30f4c28c6f1a8dc38e6a26b7
parent13601e2d24960c4503c69ff3efc159b3a2353c46 (diff)
-rw-r--r--config/kernel-mm-page-flags.m427
-rw-r--r--include/os/linux/kernel/linux/dcache_compat.h19
2 files changed, 42 insertions, 4 deletions
diff --git a/config/kernel-mm-page-flags.m4 b/config/kernel-mm-page-flags.m4
index 0bcac0b5c0a0..1c7397d19256 100644
--- a/config/kernel-mm-page-flags.m4
+++ b/config/kernel-mm-page-flags.m4
@@ -17,9 +17,36 @@ AC_DEFUN([ZFS_AC_KERNEL_MM_PAGE_FLAG_ERROR], [
])
])
+dnl #
+dnl # Linux 6.18+ uses a struct typedef (memdesc_flags_t) instead of an
+dnl # 'unsigned long' for the 'flags' field in 'struct page'.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_MM_PAGE_FLAGS_STRUCT], [
+ ZFS_LINUX_TEST_SRC([mm_page_flags_struct], [
+ #include <linux/mm.h>
+
+ static const struct page p __attribute__ ((unused)) = {
+ .flags = { .f = 0 }
+ };
+ ],[])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_MM_PAGE_FLAGS_STRUCT], [
+ AC_MSG_CHECKING([whether 'flags' in 'struct page' is a struct])
+ ZFS_LINUX_TEST_RESULT([mm_page_flags_struct], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_MM_PAGE_FLAGS_STRUCT, 1,
+ ['flags' in 'struct page' is a struct])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
+
AC_DEFUN([ZFS_AC_KERNEL_SRC_MM_PAGE_FLAGS], [
ZFS_AC_KERNEL_SRC_MM_PAGE_FLAG_ERROR
+ ZFS_AC_KERNEL_SRC_MM_PAGE_FLAGS_STRUCT
])
AC_DEFUN([ZFS_AC_KERNEL_MM_PAGE_FLAGS], [
ZFS_AC_KERNEL_MM_PAGE_FLAG_ERROR
+ ZFS_AC_KERNEL_MM_PAGE_FLAGS_STRUCT
])
diff --git a/include/os/linux/kernel/linux/dcache_compat.h b/include/os/linux/kernel/linux/dcache_compat.h
index 152e5a606f0e..f94dcda6175b 100644
--- a/include/os/linux/kernel/linux/dcache_compat.h
+++ b/include/os/linux/kernel/linux/dcache_compat.h
@@ -34,6 +34,17 @@
#define d_alias d_u.d_alias
+#ifdef HAVE_MM_PAGE_FLAGS_STRUCT
+/*
+ * Starting from Linux 6.18, the 'flags' field in 'struct page' is defined
+ * to a struct ('memdesc_flags_t' typedef) instead of an unsigned long for
+ * improved typesafety.
+ */
+#define page_flags flags.f
+#else
+#define page_flags flags
+#endif
+
/*
* Starting from Linux 5.13, flush_dcache_page() becomes an inline function
* and under some configurations, may indirectly referencing GPL-only
@@ -44,8 +55,8 @@
#include <linux/simd_powerpc.h>
#define flush_dcache_page(page) do { \
if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) && \
- test_bit(PG_dcache_clean, &(page)->flags)) \
- clear_bit(PG_dcache_clean, &(page)->flags); \
+ test_bit(PG_dcache_clean, &(page)->page_flags)) \
+ clear_bit(PG_dcache_clean, &(page)->page_flags);\
} while (0)
#endif
/*
@@ -55,8 +66,8 @@
*/
#if defined __riscv && defined HAVE_FLUSH_DCACHE_PAGE_GPL_ONLY
#define flush_dcache_page(page) do { \
- if (test_bit(PG_dcache_clean, &(page)->flags)) \
- clear_bit(PG_dcache_clean, &(page)->flags); \
+ if (test_bit(PG_dcache_clean, &(page)->page_flags)) \
+ clear_bit(PG_dcache_clean, &(page)->page_flags);\
} while (0)
#endif