[packages/zfs] - up to 2.3.5 with patches for kernel 6.18
baggins
baggins at pld-linux.org
Mon Dec 8 22:25:49 CET 2025
commit ee2adfd4d6f8b8d6e323a1bbbce0e4cfe540ae1d
Author: Jan Rękorajski <baggins at pld-linux.org>
Date: Tue Dec 9 00:25:25 2025 +0100
- up to 2.3.5 with patches for kernel 6.18
0002-Linux-6.18-replace-nth_page.patch | 41 ++++
0003-Linux-6.18-convert-ida_simple_-calls.patch | 68 ++++++
...block_device_operations-getgeo-takes-stru.patch | 109 ++++++++++
0005-Linux-6.18-replace-write_cache_pages.patch | 233 ++++++++++++++++++++
...ux-6.18-namespace-type-moved-to-ns_common.patch | 124 +++++++++++
...ric-make-internal-functions-a-little-more.patch | 143 ++++++++++++
...generic_drop_inode-and-generic_delete_ino.patch | 104 +++++++++
kernel-6.17.patch | 239 ---------------------
kernel-6.18.patch | 9 +
zfs.spec | 66 +++---
10 files changed, 871 insertions(+), 265 deletions(-)
---
diff --git a/zfs.spec b/zfs.spec
index 1df5b40..97cfe59 100644
--- a/zfs.spec
+++ b/zfs.spec
@@ -24,20 +24,27 @@ exit 1
%define _duplicate_files_terminate_build 0
-%define rel 2
+%define rel 1
%define pname zfs
Summary: Native Linux port of the ZFS filesystem
Summary(pl.UTF-8): Natywny linuksowy port systemu plików ZFS
Name: %{pname}%{?_pld_builder:%{?with_kernel:-kernel}}%{_alt_kernel}
-Version: 2.3.4
+Version: 2.3.5
Release: %{rel}%{?_pld_builder:%{?with_kernel:@%{_kernel_ver_str}}}
License: CDDL
Group: Applications/System
Source0: https://github.com/openzfs/zfs/releases/download/zfs-%{version}/%{pname}-%{version}.tar.gz
-# Source0-md5: 33be66d78e53ad63fcd7ed4ed7703cb7
+# Source0-md5: b80409d3de17ae0c74ed15a29e27c032
Patch0: initdir.patch
Patch1: pld.patch
-Patch2: kernel-6.17.patch
+Patch2: kernel-6.18.patch
+Patch3: 0002-Linux-6.18-replace-nth_page.patch
+Patch4: 0003-Linux-6.18-convert-ida_simple_-calls.patch
+Patch5: 0004-Linux-6.18-block_device_operations-getgeo-takes-stru.patch
+Patch6: 0005-Linux-6.18-replace-write_cache_pages.patch
+Patch7: 0006-Linux-6.18-namespace-type-moved-to-ns_common.patch
+Patch8: 0007-sha256_generic-make-internal-functions-a-little-more.patch
+Patch9: 0008-Linux-6.18-generic_drop_inode-and-generic_delete_ino.patch
URL: https://zfsonlinux.org/
BuildRequires: autoconf >= 2.50
BuildRequires: automake
@@ -263,9 +270,16 @@ p=`pwd`\
%prep
%setup -q -n %{pname}-%{version}
-%patch -P 0 -p1
-%patch -P 1 -p1
-%patch -P 2 -p1
+%patch -P0 -p1
+%patch -P1 -p1
+%patch -P2 -p1
+%patch -P3 -p1
+%patch -P4 -p1
+%patch -P5 -p1
+%patch -P6 -p1
+%patch -P7 -p1
+%patch -P8 -p1
+%patch -P9 -p1
%{__sed} -E -i -e '1s,#!\s*/usr/bin/env\s+python3(\s|$),#!%{__python3}\1,' \
cmd/arc_summary
@@ -532,27 +546,27 @@ rm -rf $RPM_BUILD_ROOT
%files libs
%defattr(644,root,root,755)
-%attr(755,root,root) %{_libdir}/libnvpair.so.*.*.*
-%attr(755,root,root) %ghost %{_libdir}/libnvpair.so.3
-%attr(755,root,root) %{_libdir}/libuutil.so.*.*.*
-%attr(755,root,root) %ghost %{_libdir}/libuutil.so.3
-%attr(755,root,root) %{_libdir}/libzfs.so.*.*.*
-%attr(755,root,root) %ghost %{_libdir}/libzfs.so.6
-%attr(755,root,root) %{_libdir}/libzfs_core.so.*.*.*
-%attr(755,root,root) %ghost %{_libdir}/libzfs_core.so.3
-%attr(755,root,root) %{_libdir}/libzfsbootenv.so.*.*.*
-%attr(755,root,root) %ghost %{_libdir}/libzfsbootenv.so.1
-%attr(755,root,root) %{_libdir}/libzpool.so.*.*.*
-%attr(755,root,root) %ghost %{_libdir}/libzpool.so.6
+%{_libdir}/libnvpair.so.*.*.*
+%ghost %{_libdir}/libnvpair.so.3
+%{_libdir}/libuutil.so.*.*.*
+%ghost %{_libdir}/libuutil.so.3
+%{_libdir}/libzfs.so.*.*.*
+%ghost %{_libdir}/libzfs.so.6
+%{_libdir}/libzfs_core.so.*.*.*
+%ghost %{_libdir}/libzfs_core.so.3
+%{_libdir}/libzfsbootenv.so.*.*.*
+%ghost %{_libdir}/libzfsbootenv.so.1
+%{_libdir}/libzpool.so.*.*.*
+%ghost %{_libdir}/libzpool.so.6
%files devel
%defattr(644,root,root,755)
-%attr(755,root,root) %{_libdir}/libnvpair.so
-%attr(755,root,root) %{_libdir}/libuutil.so
-%attr(755,root,root) %{_libdir}/libzfs.so
-%attr(755,root,root) %{_libdir}/libzfs_core.so
-%attr(755,root,root) %{_libdir}/libzfsbootenv.so
-%attr(755,root,root) %{_libdir}/libzpool.so
+%{_libdir}/libnvpair.so
+%{_libdir}/libuutil.so
+%{_libdir}/libzfs.so
+%{_libdir}/libzfs_core.so
+%{_libdir}/libzfsbootenv.so
+%{_libdir}/libzpool.so
%{_libdir}/libnvpair.la
%{_libdir}/libuutil.la
%{_libdir}/libzfs.la
@@ -599,7 +613,7 @@ rm -rf $RPM_BUILD_ROOT
%files -n pam-pam_zfs_key
%defattr(644,root,root,755)
-%attr(755,root,root) /%{_lib}/security/pam_zfs_key.so
+/%{_lib}/security/pam_zfs_key.so
%if %{with python3}
%files -n python3-pyzfs
diff --git a/0002-Linux-6.18-replace-nth_page.patch b/0002-Linux-6.18-replace-nth_page.patch
new file mode 100644
index 0000000..9b2ab14
--- /dev/null
+++ b/0002-Linux-6.18-replace-nth_page.patch
@@ -0,0 +1,41 @@
+From 9d50ee59dc13dbb376ec738808da9d95226b44fe Mon Sep 17 00:00:00 2001
+From: Rob Norris <robn at despairlabs.com>
+Date: Fri, 12 Sep 2025 09:57:53 +1000
+Subject: [PATCH 2/9] Linux 6.18: replace nth_page()
+
+Sponsored-by: https://despairlabs.com/sponsor/
+Signed-off-by: Rob Norris <robn at despairlabs.com>
+---
+ module/os/linux/zfs/abd_os.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/module/os/linux/zfs/abd_os.c b/module/os/linux/zfs/abd_os.c
+index 8a8316f63..18f2426fb 100644
+--- a/module/os/linux/zfs/abd_os.c
++++ b/module/os/linux/zfs/abd_os.c
+@@ -23,6 +23,7 @@
+ * Copyright (c) 2014 by Chunwei Chen. All rights reserved.
+ * Copyright (c) 2019 by Delphix. All rights reserved.
+ * Copyright (c) 2023, 2024, Klara Inc.
++ * Copyright (c) 2025, Rob Norris <robn at despairlabs.com>
+ */
+
+ /*
+@@ -1109,6 +1110,14 @@ abd_return_buf_copy(abd_t *abd, void *buf, size_t n)
+ #define ABD_ITER_PAGE_SIZE(page) (PAGESIZE)
+ #endif
+
++#ifndef nth_page
++/*
++ * Since 6.18 nth_page() no longer exists, and is no longer required to iterate
++ * within a single SG entry, so we replace it with a simple addition.
++ */
++#define nth_page(p, n) ((p)+(n))
++#endif
++
+ void
+ abd_iter_page(struct abd_iter *aiter)
+ {
+--
+2.52.0
+
diff --git a/0003-Linux-6.18-convert-ida_simple_-calls.patch b/0003-Linux-6.18-convert-ida_simple_-calls.patch
new file mode 100644
index 0000000..e7c6136
--- /dev/null
+++ b/0003-Linux-6.18-convert-ida_simple_-calls.patch
@@ -0,0 +1,68 @@
+From 5de4a297e7ab0f8062b550acc4e76308c675f653 Mon Sep 17 00:00:00 2001
+From: Rob Norris <robn at despairlabs.com>
+Date: Fri, 12 Sep 2025 10:03:07 +1000
+Subject: [PATCH 3/9] Linux 6.18: convert ida_simple_* calls
+
+ida_simple_get() and ida_simple_remove() are removed in 6.18. However,
+since 4.19 they have been simple wrappers around ida_alloc() and
+ida_free(), so we can just use those directly.
+
+Sponsored-by: https://despairlabs.com/sponsor/
+Signed-off-by: Rob Norris <robn at despairlabs.com>
+---
+ module/os/linux/zfs/zvol_os.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c
+index 4e66bee77..3e458e14c 100644
+--- a/module/os/linux/zfs/zvol_os.c
++++ b/module/os/linux/zfs/zvol_os.c
+@@ -1500,8 +1500,7 @@ zvol_os_remove_minor(zvol_state_t *zv)
+ if (zv->zv_zso->use_blk_mq)
+ blk_mq_free_tag_set(&zv->zv_zso->tag_set);
+
+- ida_simple_remove(&zvol_ida,
+- MINOR(zv->zv_zso->zvo_dev) >> ZVOL_MINOR_BITS);
++ ida_free(&zvol_ida, MINOR(zv->zv_zso->zvo_dev) >> ZVOL_MINOR_BITS);
+
+ cv_destroy(&zv->zv_removing_cv);
+ mutex_destroy(&zv->zv_state_lock);
+@@ -1655,7 +1655,7 @@ zvol_os_create_minor(const char *name)
+ if (zvol_inhibit_dev)
+ return (0);
+
+- idx = ida_simple_get(&zvol_ida, 0, 0, kmem_flags_convert(KM_SLEEP));
++ idx = ida_alloc(&zvol_ida, kmem_flags_convert(KM_SLEEP));
+ if (idx < 0)
+ return (SET_ERROR(-idx));
+ minor = idx << ZVOL_MINOR_BITS;
+@@ -1663,7 +1663,7 @@ zvol_os_create_minor(const char *name)
+ /* too many partitions can cause an overflow */
+ zfs_dbgmsg("zvol: create minor overflow: %s, minor %u/%u",
+ name, minor, MINOR(minor));
+- ida_simple_remove(&zvol_ida, idx);
++ ida_free(&zvol_ida, idx);
+ return (SET_ERROR(EINVAL));
+ }
+
+@@ -1671,7 +1671,7 @@ zvol_os_create_minor(const char *name)
+ if (zv) {
+ ASSERT(MUTEX_HELD(&zv->zv_state_lock));
+ mutex_exit(&zv->zv_state_lock);
+- ida_simple_remove(&zvol_ida, idx);
++ ida_free(&zvol_ida, idx);
+ return (SET_ERROR(EEXIST));
+ }
+
+@@ -1771,7 +1771,7 @@ out_doi:
+ rw_exit(&zvol_state_lock);
+ error = zvol_os_add_disk(zv->zv_zso->zvo_disk);
+ } else {
+- ida_simple_remove(&zvol_ida, idx);
++ ida_free(&zvol_ida, idx);
+ }
+
+ return (error);
+--
+2.52.0
+
diff --git a/0004-Linux-6.18-block_device_operations-getgeo-takes-stru.patch b/0004-Linux-6.18-block_device_operations-getgeo-takes-stru.patch
new file mode 100644
index 0000000..4937ac2
--- /dev/null
+++ b/0004-Linux-6.18-block_device_operations-getgeo-takes-stru.patch
@@ -0,0 +1,109 @@
+From 39db4bda8078eb83776ad7ac90ecb6cdcbd083eb Mon Sep 17 00:00:00 2001
+From: Rob Norris <robn at despairlabs.com>
+Date: Fri, 12 Sep 2025 10:23:28 +1000
+Subject: [PATCH 4/9] Linux 6.18: block_device_operations->getgeo takes struct
+ gendisk*
+
+Sponsored-by: https://despairlabs.com/sponsor/
+Signed-off-by: Rob Norris <robn at despairlabs.com>
+---
+ config/kernel-block-device-operations.m4 | 34 ++++++++++++++++++++++++
+ module/os/linux/zfs/zvol_os.c | 20 +++++++++++---
+ 2 files changed, 51 insertions(+), 3 deletions(-)
+
+diff --git a/config/kernel-block-device-operations.m4 b/config/kernel-block-device-operations.m4
+index 4ff20b9c4..1905340a9 100644
+--- a/config/kernel-block-device-operations.m4
++++ b/config/kernel-block-device-operations.m4
+@@ -119,15 +119,49 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK], [
+ ])
+ ])
+
++dnl #
++dnl # 6.18 API change
++dnl # block_device_operation->getgeo takes struct gendisk* as first arg
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [
++ ZFS_LINUX_TEST_SRC([block_device_operations_getgeo_gendisk], [
++ #include <linux/blkdev.h>
++
++ static int blk_getgeo(struct gendisk *disk, struct hd_geometry *geo)
++ {
++ (void) disk, (void) geo;
++ return (0);
++ }
++
++ static const struct block_device_operations
++ bops __attribute__ ((unused)) = {
++ .getgeo = blk_getgeo,
++ };
++ ], [], [])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [
++ AC_MSG_CHECKING([whether bops->getgeo() takes gendisk as first arg])
++ ZFS_LINUX_TEST_RESULT([block_device_operations_getgeo_gendisk], [
++ AC_MSG_RESULT(yes)
++ AC_DEFINE([HAVE_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [1],
++ [Define if getgeo() in block_device_operations takes struct gendisk * as its first arg])
++ ],[
++ AC_MSG_RESULT(no)
++ ])
++])
++
+ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
+ ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
+ ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
+ ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
+ ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
++ ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
+ ])
+
+ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS], [
+ ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
+ ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
+ ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
++ ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
+ ])
+diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c
+index 3e458e14c..fe939150b 100644
+--- a/module/os/linux/zfs/zvol_os.c
++++ b/module/os/linux/zfs/zvol_os.c
+@@ -1032,10 +1032,10 @@ zvol_os_update_volsize(zvol_state_t *zv, uint64_t volsize)
+ * tiny devices. For devices over 1 Mib a standard head and sector count
+ * is used to keep the cylinders count reasonable.
+ */
+-static int
+-zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
++static inline int
++zvol_getgeo_impl(struct gendisk *disk, struct hd_geometry *geo)
+ {
+- zvol_state_t *zv = bdev->bd_disk->private_data;
++ zvol_state_t *zv = disk->private_data;
+ sector_t sectors;
+
+ ASSERT3U(zv->zv_open_count, >, 0);
+@@ -1057,6 +1057,20 @@ zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+ return (0);
+ }
+
++#ifdef HAVE_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
++static int
++zvol_getgeo(struct gendisk *disk, struct hd_geometry *geo)
++{
++ return (zvol_getgeo_impl(disk, geo));
++}
++#else
++static int
++zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
++{
++ return (zvol_getgeo_impl(bdev->bd_disk, geo));
++}
++#endif
++
+ /*
+ * Why have two separate block_device_operations structs?
+ *
+--
+2.52.0
+
diff --git a/0005-Linux-6.18-replace-write_cache_pages.patch b/0005-Linux-6.18-replace-write_cache_pages.patch
new file mode 100644
index 0000000..2ab3bae
--- /dev/null
+++ b/0005-Linux-6.18-replace-write_cache_pages.patch
@@ -0,0 +1,233 @@
+From 76c238f1ba9fbd0123cf4f93028e70ad19a0bcd2 Mon Sep 17 00:00:00 2001
+From: Rob Norris <robn at despairlabs.com>
+Date: Fri, 12 Sep 2025 09:31:35 +1000
+Subject: [PATCH 5/9] Linux 6.18: replace write_cache_pages()
+
+Linux 6.18 removed write_cache_pages() without a usable replacement.
+Here we implement a minimal zpl_write_cache_pages() that find the dirty
+pages within the mapping, gets them into the expected state and hands
+them off to zfs_putpage(), which handles the rest.
+
+Sponsored-by: https://despairlabs.com/sponsor/
+Signed-off-by: Rob Norris <robn at despairlabs.com>
+---
+ config/kernel-writeback.m4 | 58 ++++++++++++++++++++++++++
+ config/kernel-writepage_t.m4 | 26 ------------
+ config/kernel.m4 | 4 +-
+ module/os/linux/zfs/zpl_file.c | 74 ++++++++++++++++++++++++++++++++++
+ 4 files changed, 134 insertions(+), 28 deletions(-)
+ create mode 100644 config/kernel-writeback.m4
+ delete mode 100644 config/kernel-writepage_t.m4
+
+diff --git a/config/kernel-writeback.m4 b/config/kernel-writeback.m4
+new file mode 100644
+index 000000000..334d65ef8
+--- /dev/null
++++ b/config/kernel-writeback.m4
+@@ -0,0 +1,58 @@
++AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEPAGE_T], [
++ dnl #
++ dnl # 6.3 API change
++ dnl # The writepage_t function type now has its first argument as
++ dnl # struct folio* instead of struct page*
++ dnl #
++ ZFS_LINUX_TEST_SRC([writepage_t_folio], [
++ #include <linux/writeback.h>
++ static int putpage(struct folio *folio,
++ struct writeback_control *wbc, void *data)
++ { return 0; }
++ writepage_t func = putpage;
++ ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_WRITEPAGE_T], [
++ AC_MSG_CHECKING([whether int (*writepage_t)() takes struct folio*])
++ ZFS_LINUX_TEST_RESULT([writepage_t_folio], [
++ AC_MSG_RESULT(yes)
++ AC_DEFINE(HAVE_WRITEPAGE_T_FOLIO, 1,
++ [int (*writepage_t)() takes struct folio*])
++ ],[
++ AC_MSG_RESULT(no)
++ ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITE_CACHE_PAGES], [
++ dnl #
++ dnl # 6.18 API change
++ dnl # write_cache_pages() has been removed.
++ dnl #
++ ZFS_LINUX_TEST_SRC([write_cache_pages], [
++ #include <linux/writeback.h>
++ ], [
++ (void) write_cache_pages(NULL, NULL, NULL, NULL);
++ ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_WRITE_CACHE_PAGES], [
++ AC_MSG_CHECKING([whether write_cache_pages() is available])
++ ZFS_LINUX_TEST_RESULT([write_cache_pages], [
++ AC_MSG_RESULT(yes)
++ AC_DEFINE(HAVE_WRITE_CACHE_PAGES, 1,
++ [write_cache_pages() is available])
++ ],[
++ AC_MSG_RESULT(no)
++ ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEBACK], [
++ ZFS_AC_KERNEL_SRC_WRITEPAGE_T
++ ZFS_AC_KERNEL_SRC_WRITE_CACHE_PAGES
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_WRITEBACK], [
++ ZFS_AC_KERNEL_WRITEPAGE_T
++ ZFS_AC_KERNEL_WRITE_CACHE_PAGES
++])
+diff --git a/config/kernel-writepage_t.m4 b/config/kernel-writepage_t.m4
+deleted file mode 100644
+index a82cf370c..000000000
+--- a/config/kernel-writepage_t.m4
++++ /dev/null
+@@ -1,26 +0,0 @@
+-AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEPAGE_T], [
+- dnl #
+- dnl # 6.3 API change
+- dnl # The writepage_t function type now has its first argument as
+- dnl # struct folio* instead of struct page*
+- dnl #
+- ZFS_LINUX_TEST_SRC([writepage_t_folio], [
+- #include <linux/writeback.h>
+- static int putpage(struct folio *folio,
+- struct writeback_control *wbc, void *data)
+- { return 0; }
+- writepage_t func = putpage;
+- ],[])
+-])
+-
+-AC_DEFUN([ZFS_AC_KERNEL_WRITEPAGE_T], [
+- AC_MSG_CHECKING([whether int (*writepage_t)() takes struct folio*])
+- ZFS_LINUX_TEST_RESULT([writepage_t_folio], [
+- AC_MSG_RESULT(yes)
+- AC_DEFINE(HAVE_WRITEPAGE_T_FOLIO, 1,
+- [int (*writepage_t)() takes struct folio*])
+- ],[
+- AC_MSG_RESULT(no)
+- ])
+-])
+-
+diff --git a/config/kernel.m4 b/config/kernel.m4
+index 35819e4d6..27fe76616 100644
+--- a/config/kernel.m4
++++ b/config/kernel.m4
+@@ -121,7 +121,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
+ ZFS_AC_KERNEL_SRC_IDMAP_MNT_API
+ ZFS_AC_KERNEL_SRC_IDMAP_NO_USERNS
+ ZFS_AC_KERNEL_SRC_IATTR_VFSID
+- ZFS_AC_KERNEL_SRC_WRITEPAGE_T
++ ZFS_AC_KERNEL_SRC_WRITEBACK
+ ZFS_AC_KERNEL_SRC_RECLAIMED
+ ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_TABLE
+ ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_SZ
+@@ -240,7 +240,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
+ ZFS_AC_KERNEL_IDMAP_MNT_API
+ ZFS_AC_KERNEL_IDMAP_NO_USERNS
+ ZFS_AC_KERNEL_IATTR_VFSID
+- ZFS_AC_KERNEL_WRITEPAGE_T
++ ZFS_AC_KERNEL_WRITEBACK
+ ZFS_AC_KERNEL_RECLAIMED
+ ZFS_AC_KERNEL_REGISTER_SYSCTL_TABLE
+ ZFS_AC_KERNEL_REGISTER_SYSCTL_SZ
+diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c
+index d07317b0d..02965ac8c 100644
+--- a/module/os/linux/zfs/zpl_file.c
++++ b/module/os/linux/zfs/zpl_file.c
+@@ -478,6 +479,7 @@ zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data)
+ return (ret);
+ }
+
++#ifdef HAVE_WRITE_CACHE_PAGES
+ #ifdef HAVE_WRITEPAGE_T_FOLIO
+ static int
+ zpl_putfolio(struct folio *pp, struct writeback_control *wbc, void *data)
+@@ -499,6 +501,78 @@ zpl_write_cache_pages(struct address_space *mapping,
+ #endif
+ return (result);
+ }
++#else
++static inline int
++zpl_write_cache_pages(struct address_space *mapping,
++ struct writeback_control *wbc, void *data)
++{
++ pgoff_t start = wbc->range_start >> PAGE_SHIFT;
++ pgoff_t end = wbc->range_end >> PAGE_SHIFT;
++
++ struct folio_batch fbatch;
++ folio_batch_init(&fbatch);
++
++ /*
++ * This atomically (-ish) tags all DIRTY pages in the range with
++ * TOWRITE, allowing users to continue dirtying or undirtying pages
++ * while we get on with writeback, without us treading on each other.
++ */
++ tag_pages_for_writeback(mapping, start, end);
++
++ int err = 0;
++ unsigned int npages;
++
++ /*
++ * Grab references to the TOWRITE pages just flagged. This may not get
++ * all of them, so we do it in a loop until there are none left.
++ */
++ while ((npages = filemap_get_folios_tag(mapping, &start, end,
++ PAGECACHE_TAG_TOWRITE, &fbatch)) != 0) {
++
++ /* Loop over each page and write it out. */
++ struct folio *folio;
++ while ((folio = folio_batch_next(&fbatch)) != NULL) {
++ folio_lock(folio);
++
++ /*
++ * If the folio has been remapped, or is no longer
++ * dirty, then there's nothing to do.
++ */
++ if (folio->mapping != mapping ||
++ !folio_test_dirty(folio)) {
++ folio_unlock(folio);
++ continue;
++ }
++
++ /*
++ * If writeback is already in progress, wait for it to
++ * finish. We continue after this even if the page
++ * ends up clean; zfs_putpage() will skip it if no
++ * further work is required.
++ */
++ while (folio_test_writeback(folio))
++ folio_wait_bit(folio, PG_writeback);
++
++ /*
++ * Write it out and collect any error. zfs_putpage()
++ * will clear the TOWRITE and DIRTY flags, and return
++ * with the page unlocked.
++ */
++ int ferr = zpl_putpage(&folio->page, wbc, data);
++ if (err == 0 && ferr != 0)
++ err = ferr;
++
++ /* Housekeeping for the caller. */
++ wbc->nr_to_write -= folio_nr_pages(folio);
++ }
++
++ /* Release any remaining references on the batch. */
++ folio_batch_release(&fbatch);
++ }
++
++ return (err);
++}
++#endif
+
+ static int
+ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc)
+--
+2.52.0
+
diff --git a/0006-Linux-6.18-namespace-type-moved-to-ns_common.patch b/0006-Linux-6.18-namespace-type-moved-to-ns_common.patch
new file mode 100644
index 0000000..cb7103c
--- /dev/null
+++ b/0006-Linux-6.18-namespace-type-moved-to-ns_common.patch
@@ -0,0 +1,124 @@
+From 8911360a416fb3a9fe055768017e003b2fc0d3bf Mon Sep 17 00:00:00 2001
+From: Rob Norris <robn at despairlabs.com>
+Date: Mon, 29 Sep 2025 09:16:36 +1000
+Subject: [PATCH 6/9] Linux 6.18: namespace type moved to ns_common
+
+The namespace type has moved from the namespace ops struct to the
+"common" base namespace struct. Detect this and define a macro that does
+the right thing for both versions.
+
+Sponsored-by: https://despairlabs.com/sponsor/
+Signed-off-by: Rob Norris <robn at despairlabs.com>
+---
+ config/kernel-namespace.m4 | 31 +++++++++++
+ config/kernel-userns-capabilities.m4 | 79 ----------------------------
+ config/kernel.m4 | 2 +
+ module/os/linux/spl/spl-zone.c | 19 ++++++-
+ 4 files changed, 51 insertions(+), 80 deletions(-)
+ create mode 100644 config/kernel-namespace.m4
+ delete mode 100644 config/kernel-userns-capabilities.m4
+
+diff --git a/config/kernel-namespace.m4 b/config/kernel-namespace.m4
+new file mode 100644
+index 000000000..9b0b12e4e
+--- /dev/null
++++ b/config/kernel-namespace.m4
+@@ -0,0 +1,31 @@
++dnl #
++dnl # 6.18 API change
++dnl # ns->ops->type was moved to ns->ns.ns_type (struct ns_common)
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_NS_COMMON_TYPE], [
++ ZFS_LINUX_TEST_SRC([ns_common_type], [
++ #include <linux/user_namespace.h>
++ ],[
++ struct user_namespace ns;
++ ns.ns.ns_type = 0;
++ ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_NS_COMMON_TYPE], [
++ AC_MSG_CHECKING([whether ns_type is accessible through ns_common])
++ ZFS_LINUX_TEST_RESULT([ns_common_type], [
++ AC_MSG_RESULT(yes)
++ AC_DEFINE([HAVE_NS_COMMON_TYPE], 1,
++ [Define if ns_type is accessible through ns_common])
++ ],[
++ AC_MSG_RESULT(no)
++ ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_NAMESPACE], [
++ ZFS_AC_KERNEL_SRC_NS_COMMON_TYPE
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_NAMESPACE], [
++ ZFS_AC_KERNEL_NS_COMMON_TYPE
++])
+diff --git a/config/kernel.m4 b/config/kernel.m4
+index 27fe76616..8484bcfb1 100644
+--- a/config/kernel.m4
++++ b/config/kernel.m4
+@@ -136,6 +136,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
+ ZFS_AC_KERNEL_SRC_TIMER
+ ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_WB_ERR
+ ZFS_AC_KERNEL_SRC_SOPS_FREE_INODE
++ ZFS_AC_KERNEL_SRC_NAMESPACE
+ case "$host_cpu" in
+ powerpc*)
+ ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
+@@ -256,6 +257,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
+ ZFS_AC_KERNEL_TIMER
+ ZFS_AC_KERNEL_SUPER_BLOCK_S_WB_ERR
+ ZFS_AC_KERNEL_SOPS_FREE_INODE
++ ZFS_AC_KERNEL_NAMESPACE
+ case "$host_cpu" in
+ powerpc*)
+ ZFS_AC_KERNEL_CPU_HAS_FEATURE
+diff --git a/module/os/linux/spl/spl-zone.c b/module/os/linux/spl/spl-zone.c
+index 45c2999a4..b2eae5d00 100644
+--- a/module/os/linux/spl/spl-zone.c
++++ b/module/os/linux/spl/spl-zone.c
+@@ -25,6 +25,10 @@
+ * SUCH DAMAGE.
+ */
+
++/*
++ * Copyright (c) 2025, Rob Norris <robn at despairlabs.com>
++ */
++
+ #include <sys/types.h>
+ #include <sys/sysmacros.h>
+ #include <sys/kmem.h>
+@@ -56,6 +60,19 @@ typedef struct zone_dataset {
+ } zone_dataset_t;
+
+ #ifdef CONFIG_USER_NS
++
++/*
++ * Linux 6.18 moved the generic namespace type away from ns->ops->type onto
++ * ns_common itself.
++ */
++#ifdef HAVE_NS_COMMON_TYPE
++#define ns_is_newuser(ns) \
++ ((ns)->ns_type == CLONE_NEWUSER)
++#else
++#define ns_is_newuser(ns) \
++ ((ns)->ops != NULL && (ns)->ops->type == CLONE_NEWUSER)
++#endif
++
+ /*
+ * Returns:
+ * - 0 on success
+@@ -84,7 +101,7 @@ user_ns_get(int fd, struct user_namespace **userns)
+ goto done;
+ }
+ ns = get_proc_ns(file_inode(nsfile));
+- if (ns->ops->type != CLONE_NEWUSER) {
++ if (!ns_is_newuser(ns)) {
+ error = ENOTTY;
+ goto done;
+ }
+--
+2.52.0
+
diff --git a/0007-sha256_generic-make-internal-functions-a-little-more.patch b/0007-sha256_generic-make-internal-functions-a-little-more.patch
new file mode 100644
index 0000000..57786b6
--- /dev/null
+++ b/0007-sha256_generic-make-internal-functions-a-little-more.patch
@@ -0,0 +1,143 @@
+From 3651888182ec381f95d90efbd564a207e5e17670 Mon Sep 17 00:00:00 2001
+From: Rob Norris <robn at despairlabs.com>
+Date: Mon, 29 Sep 2025 09:32:50 +1000
+Subject: [PATCH 7/9] sha256_generic: make internal functions a little more
+ private
+
+Linux 6.18 has conflicting prototypes for various sha256_* and sha512_*
+functions, which we get through a very long include chain. That's tough
+to fix right now; easier is just to rename our internal functions.
+
+Sponsored-by: https://despairlabs.com/sponsor/
+Signed-off-by: Rob Norris <robn at despairlabs.com>
+---
+ module/icp/algs/sha2/sha2_generic.c | 41 +++++++++++++++++------------
+ 1 file changed, 24 insertions(+), 17 deletions(-)
+
+diff --git a/module/icp/algs/sha2/sha2_generic.c b/module/icp/algs/sha2/sha2_generic.c
+index d0fcca798..ad707341e 100644
+--- a/module/icp/algs/sha2/sha2_generic.c
++++ b/module/icp/algs/sha2/sha2_generic.c
+@@ -77,7 +77,8 @@ static const uint32_t SHA256_K[64] = {
+ h = g, g = f, f = e, e = d + T1; \
+ d = c, c = b, b = a, a = T1 + T2;
+
+-static void sha256_generic(uint32_t state[8], const void *data, size_t num_blks)
++static void
++icp_sha256_generic(uint32_t state[8], const void *data, size_t num_blks)
+ {
+ uint64_t blk;
+
+@@ -173,7 +174,8 @@ static const uint64_t SHA512_K[80] = {
+ 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
+ };
+
+-static void sha512_generic(uint64_t state[8], const void *data, size_t num_blks)
++static void
++icp_sha512_generic(uint64_t state[8], const void *data, size_t num_blks)
+ {
+ uint64_t blk;
+
+@@ -226,7 +228,8 @@ static void sha512_generic(uint64_t state[8], const void *data, size_t num_blks)
+ }
+ }
+
+-static void sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len)
++static void
++icp_sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len)
+ {
+ uint64_t pos = ctx->count[0];
+ uint64_t total = ctx->count[1];
+@@ -258,7 +261,8 @@ static void sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len)
+ ctx->count[1] = total;
+ }
+
+-static void sha512_update(sha512_ctx *ctx, const uint8_t *data, size_t len)
++static void
++icp_sha512_update(sha512_ctx *ctx, const uint8_t *data, size_t len)
+ {
+ uint64_t pos = ctx->count[0];
+ uint64_t total = ctx->count[1];
+@@ -290,7 +294,8 @@ static void sha512_update(sha512_ctx *ctx, const uint8_t *data, size_t len)
+ ctx->count[1] = total;
+ }
+
+-static void sha256_final(sha256_ctx *ctx, uint8_t *result, int bits)
++static void
++icp_sha256_final(sha256_ctx *ctx, uint8_t *result, int bits)
+ {
+ uint64_t mlen, pos = ctx->count[0];
+ uint8_t *m = ctx->wbuf;
+@@ -334,7 +339,8 @@ static void sha256_final(sha256_ctx *ctx, uint8_t *result, int bits)
+ memset(ctx, 0, sizeof (*ctx));
+ }
+
+-static void sha512_final(sha512_ctx *ctx, uint8_t *result, int bits)
++static void
++icp_sha512_final(sha512_ctx *ctx, uint8_t *result, int bits)
+ {
+ uint64_t mlen, pos = ctx->count[0];
+ uint8_t *m = ctx->wbuf, *r;
+@@ -461,14 +467,14 @@ SHA2Update(SHA2_CTX *ctx, const void *data, size_t len)
+
+ switch (ctx->algotype) {
+ case SHA256:
+- sha256_update(&ctx->sha256, data, len);
++ icp_sha256_update(&ctx->sha256, data, len);
+ break;
+ case SHA512:
+ case SHA512_HMAC_MECH_INFO_TYPE:
+- sha512_update(&ctx->sha512, data, len);
++ icp_sha512_update(&ctx->sha512, data, len);
+ break;
+ case SHA512_256:
+- sha512_update(&ctx->sha512, data, len);
++ icp_sha512_update(&ctx->sha512, data, len);
+ break;
+ }
+ }
+@@ -479,32 +485,33 @@ SHA2Final(void *digest, SHA2_CTX *ctx)
+ {
+ switch (ctx->algotype) {
+ case SHA256:
+- sha256_final(&ctx->sha256, digest, 256);
++ icp_sha256_final(&ctx->sha256, digest, 256);
+ break;
+ case SHA512:
+ case SHA512_HMAC_MECH_INFO_TYPE:
+- sha512_final(&ctx->sha512, digest, 512);
++ icp_sha512_final(&ctx->sha512, digest, 512);
+ break;
+ case SHA512_256:
+- sha512_final(&ctx->sha512, digest, 256);
++ icp_sha512_final(&ctx->sha512, digest, 256);
+ break;
+ }
+ }
+
+ /* the generic implementation is always okay */
+-static boolean_t sha2_is_supported(void)
++static boolean_t
++icp_sha2_is_supported(void)
+ {
+ return (B_TRUE);
+ }
+
+ const sha256_ops_t sha256_generic_impl = {
+ .name = "generic",
+- .transform = sha256_generic,
+- .is_supported = sha2_is_supported
++ .transform = icp_sha256_generic,
++ .is_supported = icp_sha2_is_supported
+ };
+
+ const sha512_ops_t sha512_generic_impl = {
+ .name = "generic",
+- .transform = sha512_generic,
+- .is_supported = sha2_is_supported
++ .transform = icp_sha512_generic,
++ .is_supported = icp_sha2_is_supported
+ };
+--
+2.52.0
+
diff --git a/0008-Linux-6.18-generic_drop_inode-and-generic_delete_ino.patch b/0008-Linux-6.18-generic_drop_inode-and-generic_delete_ino.patch
new file mode 100644
index 0000000..20c3d3e
--- /dev/null
+++ b/0008-Linux-6.18-generic_drop_inode-and-generic_delete_ino.patch
@@ -0,0 +1,104 @@
+From fe8b50f09fe69d3ae672d75593ec11b6d2b3f73f Mon Sep 17 00:00:00 2001
+From: Rob Norris <robn at despairlabs.com>
+Date: Mon, 29 Sep 2025 09:51:06 +1000
+Subject: [PATCH 8/9] Linux 6.18: generic_drop_inode() and
+ generic_delete_inode() renamed
+
+Sponsored-by: https://despairlabs.com/sponsor/
+Signed-off-by: Rob Norris <robn at despairlabs.com>
+---
+ config/kernel-drop-inode.m4 | 24 ++++++++++++++++++++++
+ config/kernel.m4 | 2 ++
+ include/os/linux/kernel/linux/vfs_compat.h | 7 +++++++
+ module/os/linux/zfs/zpl_super.c | 4 +++-
+ 4 files changed, 36 insertions(+), 1 deletion(-)
+ create mode 100644 config/kernel-drop-inode.m4
+
+diff --git a/config/kernel-drop-inode.m4 b/config/kernel-drop-inode.m4
+new file mode 100644
+index 000000000..6f2b12cad
+--- /dev/null
++++ b/config/kernel-drop-inode.m4
+@@ -0,0 +1,24 @@
++dnl #
++dnl # 6.18 API change
++dnl # - generic_drop_inode() renamed to inode_generic_drop()
++dnl # - generic_delete_inode() renamed to inode_just_drop()
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GENERIC_DROP], [
++ ZFS_LINUX_TEST_SRC([inode_generic_drop], [
++ #include <linux/fs.h>
++ ],[
++ struct inode *ip = NULL;
++ inode_generic_drop(ip);
++ ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_GENERIC_DROP], [
++ AC_MSG_CHECKING([whether inode_generic_drop() exists])
++ ZFS_LINUX_TEST_RESULT([inode_generic_drop], [
++ AC_MSG_RESULT(yes)
++ AC_DEFINE(HAVE_INODE_GENERIC_DROP, 1,
++ [inode_generic_drop() exists])
++ ],[
++ AC_MSG_RESULT(no)
++ ])
++])
+diff --git a/config/kernel.m4 b/config/kernel.m4
+index 8484bcfb1..40b7de739 100644
+--- a/config/kernel.m4
++++ b/config/kernel.m4
+@@ -137,6 +137,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
+ ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_WB_ERR
+ ZFS_AC_KERNEL_SRC_SOPS_FREE_INODE
+ ZFS_AC_KERNEL_SRC_NAMESPACE
++ ZFS_AC_KERNEL_SRC_INODE_GENERIC_DROP
+ case "$host_cpu" in
+ powerpc*)
+ ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
+@@ -258,6 +259,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
+ ZFS_AC_KERNEL_SUPER_BLOCK_S_WB_ERR
+ ZFS_AC_KERNEL_SOPS_FREE_INODE
+ ZFS_AC_KERNEL_NAMESPACE
++ ZFS_AC_KERNEL_INODE_GENERIC_DROP
+ case "$host_cpu" in
+ powerpc*)
+ ZFS_AC_KERNEL_CPU_HAS_FEATURE
+diff --git a/include/os/linux/kernel/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h
+index cbf14e283..d9dc904bc 100644
+--- a/include/os/linux/kernel/linux/vfs_compat.h
++++ b/include/os/linux/kernel/linux/vfs_compat.h
+@@ -23,6 +23,7 @@
+ /*
+ * Copyright (C) 2011 Lawrence Livermore National Security, LLC.
+ * Copyright (C) 2015 Jörg Thalheim.
++ * Copyright (c) 2025, Rob Norris <robn at despairlabs.com>
+ */
+
+ #ifndef _ZFS_VFS_H
+@@ -262,4 +263,10 @@ zpl_is_32bit_api(void)
+ #define zpl_generic_fillattr(user_ns, ip, sp) generic_fillattr(ip, sp)
+ #endif
+
++#ifdef HAVE_INODE_GENERIC_DROP
++/* 6.18 API change. These were renamed, alias the old names to the new. */
++#define generic_delete_inode(ip) inode_just_drop(ip)
++#define generic_drop_inode(ip) inode_generic_drop(ip)
++#endif
++
+ #endif /* _ZFS_VFS_H */
+diff --git a/module/os/linux/zfs/zpl_super.c b/module/os/linux/zfs/zpl_super.c
+index 444948d03..347b35250 100644
+--- a/module/os/linux/zfs/zpl_super.c
++++ b/module/os/linux/zfs/zpl_super.c
+@@ -33,6 +34,7 @@
+ #include <sys/zpl.h>
+ #include <linux/iversion.h>
+ #include <linux/version.h>
++#include <linux/vfs_compat.h>
+
+
+ static struct inode *
+--
+2.52.0
+
diff --git a/kernel-6.17.patch b/kernel-6.17.patch
deleted file mode 100644
index c516ce3..0000000
--- a/kernel-6.17.patch
+++ /dev/null
@@ -1,239 +0,0 @@
-From 0df91abe821e52bc63c59f4fd0548835081dc3ad Mon Sep 17 00:00:00 2001
-From: Rob Norris <robn at despairlabs.com>
-Date: Thu, 31 Jul 2025 13:12:43 +1000
-Subject: [PATCH] Linux 6.17: d_set_d_op() is no longer available
-
-We only have extremely narrow uses, so move it all into a single
-function that does only what we need, with and without d_set_d_op().
-
-Sponsored-by: https://despairlabs.com/sponsor/
-Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
-Reviewed-by: Tony Hutter <hutter2 at llnl.gov>
-Signed-off-by: Rob Norris <robn at despairlabs.com>
-Closes #17621
----
- config/kernel-dentry-operations.m4 | 10 +++-
- include/os/linux/kernel/linux/dcache_compat.h | 26 ---------
- module/os/linux/zfs/zpl_ctldir.c | 55 ++++++++++++++++---
- 3 files changed, 55 insertions(+), 36 deletions(-)
-
-diff --git a/config/kernel-dentry-operations.m4 b/config/kernel-dentry-operations.m4
-index 5a5c93b1eee9..6d87ad0e0710 100644
---- a/config/kernel-dentry-operations.m4
-+++ b/config/kernel-dentry-operations.m4
-@@ -0,0 +1,82 @@
-+dnl #
-+dnl # 2.6.28 API change
-+dnl # Added d_obtain_alias() helper function.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_D_OBTAIN_ALIAS], [
-+ ZFS_LINUX_TEST_SRC([d_obtain_alias], [
-+ #include <linux/dcache.h>
-+ ], [
-+ d_obtain_alias(NULL);
-+ ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_D_OBTAIN_ALIAS], [
-+ AC_MSG_CHECKING([whether d_obtain_alias() is available])
-+ ZFS_LINUX_TEST_RESULT_SYMBOL([d_obtain_alias],
-+ [d_obtain_alias], [fs/dcache.c], [
-+ AC_MSG_RESULT(yes)
-+ ], [
-+ ZFS_LINUX_TEST_ERROR([d_obtain_alias()])
-+ ])
-+])
-+
-+dnl #
-+dnl # 2.6.38 API change
-+dnl # Added d_set_d_op() helper function.
-+dnl #
-+dnl # 6.17 API change
-+dnl # d_set_d_op() removed. No direct replacement.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_D_SET_D_OP], [
-+ ZFS_LINUX_TEST_SRC([d_set_d_op], [
-+ #include <linux/dcache.h>
-+ ], [
-+ d_set_d_op(NULL, NULL);
-+ ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_D_SET_D_OP], [
-+ AC_MSG_CHECKING([whether d_set_d_op() is available])
-+ ZFS_LINUX_TEST_RESULT([d_set_d_op], [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_D_SET_D_OP, 1,
-+ [Define if d_set_d_op() is available])
-+ ], [
-+ AC_MSG_RESULT(no)
-+ ])
-+])
-+
-+dnl #
-+dnl # 6.17 API change
-+dnl # sb->s_d_op removed; set_default_d_op(sb, dop) added
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SET_DEFAULT_D_OP], [
-+ ZFS_LINUX_TEST_SRC([set_default_d_op], [
-+ #include <linux/dcache.h>
-+ ], [
-+ set_default_d_op(NULL, NULL);
-+ ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SET_DEFAULT_D_OP], [
-+ AC_MSG_CHECKING([whether set_default_d_op() is available])
-+ ZFS_LINUX_TEST_RESULT([set_default_d_op], [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_SET_DEFAULT_D_OP, 1,
-+ [Define if set_default_d_op() is available])
-+ ], [
-+ AC_MSG_RESULT(no)
-+ ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY], [
-+ ZFS_AC_KERNEL_SRC_D_OBTAIN_ALIAS
-+ ZFS_AC_KERNEL_SRC_D_SET_D_OP
-+ ZFS_AC_KERNEL_SRC_SET_DEFAULT_D_OP
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_DENTRY], [
-+ ZFS_AC_KERNEL_D_OBTAIN_ALIAS
-+ ZFS_AC_KERNEL_D_SET_D_OP
-+ ZFS_AC_KERNEL_SET_DEFAULT_D_OP
-+])
-diff --git a/include/os/linux/kernel/linux/dcache_compat.h b/include/os/linux/kernel/linux/dcache_compat.h
-index 16e8a319a5f8..152e5a606f0e 100644
---- a/include/os/linux/kernel/linux/dcache_compat.h
-+++ b/include/os/linux/kernel/linux/dcache_compat.h
-@@ -60,32 +60,6 @@
- } while (0)
- #endif
-
--/*
-- * 2.6.30 API change,
-- * The const keyword was added to the 'struct dentry_operations' in
-- * the dentry structure. To handle this we define an appropriate
-- * dentry_operations_t typedef which can be used.
-- */
--typedef const struct dentry_operations dentry_operations_t;
--
--/*
-- * 2.6.38 API addition,
-- * Added d_clear_d_op() helper function which clears some flags and the
-- * registered dentry->d_op table. This is required because d_set_d_op()
-- * issues a warning when the dentry operations table is already set.
-- * For the .zfs control directory to work properly we must be able to
-- * override the default operations table and register custom .d_automount
-- * and .d_revalidate callbacks.
-- */
--static inline void
--d_clear_d_op(struct dentry *dentry)
--{
-- dentry->d_op = NULL;
-- dentry->d_flags &= ~(
-- DCACHE_OP_HASH | DCACHE_OP_COMPARE |
-- DCACHE_OP_REVALIDATE | DCACHE_OP_DELETE);
--}
--
- /*
- * Walk and invalidate all dentry aliases of an inode
- * unless it's a mountpoint
-diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c
-index 48dae79a2373..81ac26cb0c93 100644
---- a/module/os/linux/zfs/zpl_ctldir.c
-+++ b/module/os/linux/zfs/zpl_ctldir.c
-@@ -202,7 +202,7 @@ zpl_snapdir_revalidate(struct dentry *dentry, unsigned int flags)
- return (!!dentry->d_inode);
- }
-
--static dentry_operations_t zpl_dops_snapdirs = {
-+static const struct dentry_operations zpl_dops_snapdirs = {
- /*
- * Auto mounting of snapshots is only supported for 2.6.37 and
- * newer kernels. Prior to this kernel the ops->follow_link()
-@@ -215,6 +215,51 @@ static dentry_operations_t zpl_dops_snapdirs = {
- .d_revalidate = zpl_snapdir_revalidate,
- };
-
-+/*
-+ * For the .zfs control directory to work properly we must be able to override
-+ * the default operations table and register custom .d_automount and
-+ * .d_revalidate callbacks.
-+ */
-+static void
-+set_snapdir_dentry_ops(struct dentry *dentry, unsigned int extraflags) {
-+ static const unsigned int op_flags =
-+ DCACHE_OP_HASH | DCACHE_OP_COMPARE |
-+ DCACHE_OP_REVALIDATE | DCACHE_OP_DELETE |
-+ DCACHE_OP_PRUNE | DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_REAL;
-+
-+#ifdef HAVE_D_SET_D_OP
-+ /*
-+ * d_set_d_op() will set the DCACHE_OP_ flags according to what it
-+ * finds in the passed dentry_operations, so we don't have to.
-+ *
-+ * We clear the flags and the old op table before calling d_set_d_op()
-+ * because issues a warning when the dentry operations table is already
-+ * set.
-+ */
-+ dentry->d_op = NULL;
-+ dentry->d_flags &= ~op_flags;
-+ d_set_d_op(dentry, &zpl_dops_snapdirs);
-+ dentry->d_flags |= extraflags;
-+#else
-+ /*
-+ * Since 6.17 there's no exported way to modify dentry ops, so we have
-+ * to reach in and do it ourselves. This should be safe for our very
-+ * narrow use case, which is to create or splice in an entry to give
-+ * access to a snapshot.
-+ *
-+ * We need to set the op flags directly. We hardcode
-+ * DCACHE_OP_REVALIDATE because that's the only operation we have; if
-+ * we ever extend zpl_dops_snapdirs we will need to update the op flags
-+ * to match.
-+ */
-+ spin_lock(&dentry->d_lock);
-+ dentry->d_op = &zpl_dops_snapdirs;
-+ dentry->d_flags &= ~op_flags;
-+ dentry->d_flags |= DCACHE_OP_REVALIDATE | extraflags;
-+ spin_unlock(&dentry->d_lock);
-+#endif
-+}
-+
- static struct dentry *
- zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
- unsigned int flags)
-@@ -236,10 +281,7 @@ zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
- return (ERR_PTR(error));
-
- ASSERT(error == 0 || ip == NULL);
-- d_clear_d_op(dentry);
-- d_set_d_op(dentry, &zpl_dops_snapdirs);
-- dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
--
-+ set_snapdir_dentry_ops(dentry, DCACHE_NEED_AUTOMOUNT);
- return (d_splice_alias(ip, dentry));
- }
-
-@@ -373,8 +415,7 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
-
- error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0);
- if (error == 0) {
-- d_clear_d_op(dentry);
-- d_set_d_op(dentry, &zpl_dops_snapdirs);
-+ set_snapdir_dentry_ops(dentry, 0);
- d_instantiate(dentry, ip);
- }
-
---- zfs-2.3.4/META~ 2025-08-25 22:57:18.000000000 +0200
-+++ zfs-2.3.4/META 2025-10-05 00:32:44.599997606 +0200
-@@ -6,5 +6,5 @@
- Release-Tags: relext
- License: CDDL
- Author: OpenZFS
--Linux-Maximum: 6.16
-+Linux-Maximum: 6.17
- Linux-Minimum: 4.18
diff --git a/kernel-6.18.patch b/kernel-6.18.patch
new file mode 100644
index 0000000..12b839e
--- /dev/null
+++ b/kernel-6.18.patch
@@ -0,0 +1,9 @@
+--- zfs-2.3.4/META~ 2025-08-25 22:57:18.000000000 +0200
++++ zfs-2.3.4/META 2025-10-05 00:32:44.599997606 +0200
+@@ -6,5 +6,5 @@
+ Release-Tags: relext
+ License: CDDL
+ Author: OpenZFS
+-Linux-Maximum: 6.17
++Linux-Maximum: 6.18
+ Linux-Minimum: 4.18
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/zfs.git/commitdiff/ee2adfd4d6f8b8d6e323a1bbbce0e4cfe540ae1d
More information about the pld-cvs-commit
mailing list