[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